我编写了一个全局键盘钩子dll,希望能够在任何进行中,点击F8或F9键时,采用模拟键盘输入的方式(keybd_event)输入某个字符串。现在的问题是:当我的光标在装载钩子的的程序界面上时,能够将预设的字符串用键盘模拟按键的方式输入窗口的Edit控件。但是当焦点在其他可执行文件,例如记事本中,不能模拟键入任何内容。
系统代码如下:
// LaunchDLL.cpp : Defines the initialization routines for the DLL.
//
#define _WIN32_WINNT 0x0500 //设置系统版本, 确保可以使用底层
#include "stdafx.h"
#include <windows.h>
#include "LaunchDLL.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endifHHOOK Hook;
char userID[128];
char userPsw[128];
int g_nIDlen;
int g_nPswLen;
LPFNKEYBOARDPROC g_lpfnKeyboardProc;// 键盘钩子回调函数指针LRESULT CALLBACK LowLevelKeyboardProc(int nCode,WPARAM wParam,LPARAM lParam);
int GetCharKey(char ch, BOOL &shift);//
// Note!
//
// If this DLL is dynamically linked against the MFC
// DLLs, any functions exported from this DLL which
// call into MFC must have the AFX_MANAGE_STATE macro
// added at the very beginning of the function.
//
// For example:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // normal function body here
// }
//
// It is very important that this macro appear in each
// function, prior to any calls into MFC. This means that
// it must appear as the first statement within the
// function, even before any object variable declarations
// as their constructors may generate calls into the MFC
// DLL.
//
// Please see MFC Technical Notes 33 and 58 for additional
// details.
///////////////////////////////////////////////////////////////////////////////
// CLaunchDLLAppBEGIN_MESSAGE_MAP(CLaunchDLLApp, CWinApp)
//{{AFX_MSG_MAP(CLaunchDLLApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CLaunchDLLApp construction
CLaunchDLLApp::CLaunchDLLApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}/////////////////////////////////////////////////////////////////////////////
// The one and only CLaunchDLLApp objectCLaunchDLLApp theApp;
DllExport void WINAPI InstallLaunchEv()
{
//调用SDK中的API函数SetWindowsHookEx来安装这个钩子函数 Hook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD,
(HOOKPROC)LowLevelKeyboardProc,
theApp.m_hInstance,
0);
}DllExport void WINAPI UnInstallLaunchEv()
{
UnhookWindowsHookEx(Hook);}LRESULT CALLBACK LowLevelKeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
LRESULT Result=CallNextHookEx(Hook,nCode,wParam,lParam);
if(((DWORD)lParam&0x40000000) && (HC_ACTION==nCode))
{
if( wParam == VK_F8 || wParam == VK_F9){
int iCapital=GetKeyState(0x14);
int iNumLock=GetKeyState(0x90);
BOOL bShift= FALSE;
BOOL bCapital=(iCapital&1)==1;
BOOL bNumLock=(iNumLock&1)==1; if(bCapital){
keybd_event(0x14,0,0,0);
keybd_event(0x14,0,KEYEVENTF_KEYUP,0);
}
if(bNumLock){
keybd_event(0x90,0,0,0);
keybd_event(0x90,0,KEYEVENTF_KEYUP,0);
} //userID
if(wParam == VK_F8 ){
int &len = g_nIDlen;
int intch = 0;
for(int i=0;i<len;i++)
{
intch = GetCharKey(userID[i],bShift) ;
if(bShift)
keybd_event(0x10,0,0,0);
keybd_event(intch,0,0,0);
keybd_event(intch,0,KEYEVENTF_KEYUP,0);
if(bShift)
keybd_event(0x10,0,KEYEVENTF_KEYUP,0); }
}
else if(wParam == VK_F9 ){
int len = strlen(userPsw);
int intch = 0;
for(int i=0;i<len;i++)
{ intch = GetCharKey(userPsw[i],bShift) ;
if(bShift)
keybd_event(0x10,0,0,0);
keybd_event(intch,0,0,0);
keybd_event(intch,0,KEYEVENTF_KEYUP,0);
if(bShift)
keybd_event(0x10,0,KEYEVENTF_KEYUP,0);
}
} //end if wParam == VK_F9
}// end if( wParam == VK_F8 || wParam == VK_F9)
}//end if(((DWORD)lParam&0x40000000) && (HC_ACTION==nCode))
return Result;
}//void WINAPI SetFuncProc(char**msg,int length,LPFNKEYBOARDPROC lpfnKeyboardProc)
void WINAPI SetFuncProc(char* chID ,char *chPsw )
{
// 将用户传来的 keycode 数组保存在全局变量中
g_nIDlen = strlen(chID);
strcpy(userID,chID);
userID[g_nIDlen] = '\0';
g_nPswLen = strlen(chPsw);
strcpy(userPsw,chPsw);
userPsw[g_nPswLen] = '\0';
// g_lpfnKeyboardProc = lpfnKeyboardProc;
}
int GetCharKey(char ch, BOOL &shift){ int res = 0;
if (ch >= 'a' && ch <= 'z'){
shift = FALSE;
return 65 + ch -'a' ;
}
else if( ch>='A' && ch <='Z'){
shift = TRUE;
return 65 + ch -'A';
}
else if( ch >='0' && ch <= '9'){
shift = FALSE;
return 48 + ch - '0';
}
else {
switch(ch)
{
case '!':
res = 49;
shift = TRUE;
break;
case '@':
res=50;
shift = TRUE;
break;
case '#' :
res =51;
shift = TRUE;
break;
case '$':
res =52;
shift = TRUE;
break;
case '%':
res=53;
shift = TRUE;
break;
case '^':
res= 54;
shift = TRUE;
break;
case '&' :
res=55;
shift = TRUE;
break;
case '*':
res=56;
shift = TRUE;
break;
case '(' :
res =57;
shift = TRUE;
break;
case ')' :
res=48;
shift = TRUE;
break;
case ';' :
res = 186;
shift = FALSE;
break;
case ':' :
res = 186 ;
shift = TRUE;
break;
case '=' :
res = 187;
shift = FALSE;
break;
case '+':
res = 187 ;
shift = TRUE;
break;
case ',' :
res = 188;
shift = FALSE;
break;
case '<':
res = 188;
shift = TRUE;
break;
case '-' :
res = 189;
shift = FALSE;
break;
case '_' :
res = 189 ;
shift = TRUE;
break;
case '.' :
res = 190;
shift = FALSE;
break;
case '>' :
res = 190 ;
shift = TRUE;
break;
case '/' :
res = 191;
shift = FALSE;
break;
case '?':
res = 191;
shift = TRUE;
break;
case '`' :
res = 192;
shift = FALSE;
break;
case '~' :
res = 192;
shift = TRUE;
break;
case '[' :
res = 219;
shift = FALSE;
break;
case '{' :
res = 219;
shift = TRUE;
break;
case '\\' :
res = 220;
shift = FALSE;
break;
case '|' :
res = 220;
shift = TRUE;
break;
case ']':
res = 221;
shift = FALSE;
break;
case '}' :
res = 221;
shift = TRUE;
break;
case '\'' :
res = 222;
shift = FALSE;
break;
case '\"' :
res = 222;
shift = TRUE;
break;
case ' ':
res = 32;
shift = FALSE;
default :
res = 0 ;
break;
}
}// end else
return 0;
}
系统代码如下:
// LaunchDLL.cpp : Defines the initialization routines for the DLL.
//
#define _WIN32_WINNT 0x0500 //设置系统版本, 确保可以使用底层
#include "stdafx.h"
#include <windows.h>
#include "LaunchDLL.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endifHHOOK Hook;
char userID[128];
char userPsw[128];
int g_nIDlen;
int g_nPswLen;
LPFNKEYBOARDPROC g_lpfnKeyboardProc;// 键盘钩子回调函数指针LRESULT CALLBACK LowLevelKeyboardProc(int nCode,WPARAM wParam,LPARAM lParam);
int GetCharKey(char ch, BOOL &shift);//
// Note!
//
// If this DLL is dynamically linked against the MFC
// DLLs, any functions exported from this DLL which
// call into MFC must have the AFX_MANAGE_STATE macro
// added at the very beginning of the function.
//
// For example:
//
// extern "C" BOOL PASCAL EXPORT ExportedFunction()
// {
// AFX_MANAGE_STATE(AfxGetStaticModuleState());
// // normal function body here
// }
//
// It is very important that this macro appear in each
// function, prior to any calls into MFC. This means that
// it must appear as the first statement within the
// function, even before any object variable declarations
// as their constructors may generate calls into the MFC
// DLL.
//
// Please see MFC Technical Notes 33 and 58 for additional
// details.
///////////////////////////////////////////////////////////////////////////////
// CLaunchDLLAppBEGIN_MESSAGE_MAP(CLaunchDLLApp, CWinApp)
//{{AFX_MSG_MAP(CLaunchDLLApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CLaunchDLLApp construction
CLaunchDLLApp::CLaunchDLLApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}/////////////////////////////////////////////////////////////////////////////
// The one and only CLaunchDLLApp objectCLaunchDLLApp theApp;
DllExport void WINAPI InstallLaunchEv()
{
//调用SDK中的API函数SetWindowsHookEx来安装这个钩子函数 Hook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD,
(HOOKPROC)LowLevelKeyboardProc,
theApp.m_hInstance,
0);
}DllExport void WINAPI UnInstallLaunchEv()
{
UnhookWindowsHookEx(Hook);}LRESULT CALLBACK LowLevelKeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
LRESULT Result=CallNextHookEx(Hook,nCode,wParam,lParam);
if(((DWORD)lParam&0x40000000) && (HC_ACTION==nCode))
{
if( wParam == VK_F8 || wParam == VK_F9){
int iCapital=GetKeyState(0x14);
int iNumLock=GetKeyState(0x90);
BOOL bShift= FALSE;
BOOL bCapital=(iCapital&1)==1;
BOOL bNumLock=(iNumLock&1)==1; if(bCapital){
keybd_event(0x14,0,0,0);
keybd_event(0x14,0,KEYEVENTF_KEYUP,0);
}
if(bNumLock){
keybd_event(0x90,0,0,0);
keybd_event(0x90,0,KEYEVENTF_KEYUP,0);
} //userID
if(wParam == VK_F8 ){
int &len = g_nIDlen;
int intch = 0;
for(int i=0;i<len;i++)
{
intch = GetCharKey(userID[i],bShift) ;
if(bShift)
keybd_event(0x10,0,0,0);
keybd_event(intch,0,0,0);
keybd_event(intch,0,KEYEVENTF_KEYUP,0);
if(bShift)
keybd_event(0x10,0,KEYEVENTF_KEYUP,0); }
}
else if(wParam == VK_F9 ){
int len = strlen(userPsw);
int intch = 0;
for(int i=0;i<len;i++)
{ intch = GetCharKey(userPsw[i],bShift) ;
if(bShift)
keybd_event(0x10,0,0,0);
keybd_event(intch,0,0,0);
keybd_event(intch,0,KEYEVENTF_KEYUP,0);
if(bShift)
keybd_event(0x10,0,KEYEVENTF_KEYUP,0);
}
} //end if wParam == VK_F9
}// end if( wParam == VK_F8 || wParam == VK_F9)
}//end if(((DWORD)lParam&0x40000000) && (HC_ACTION==nCode))
return Result;
}//void WINAPI SetFuncProc(char**msg,int length,LPFNKEYBOARDPROC lpfnKeyboardProc)
void WINAPI SetFuncProc(char* chID ,char *chPsw )
{
// 将用户传来的 keycode 数组保存在全局变量中
g_nIDlen = strlen(chID);
strcpy(userID,chID);
userID[g_nIDlen] = '\0';
g_nPswLen = strlen(chPsw);
strcpy(userPsw,chPsw);
userPsw[g_nPswLen] = '\0';
// g_lpfnKeyboardProc = lpfnKeyboardProc;
}
int GetCharKey(char ch, BOOL &shift){ int res = 0;
if (ch >= 'a' && ch <= 'z'){
shift = FALSE;
return 65 + ch -'a' ;
}
else if( ch>='A' && ch <='Z'){
shift = TRUE;
return 65 + ch -'A';
}
else if( ch >='0' && ch <= '9'){
shift = FALSE;
return 48 + ch - '0';
}
else {
switch(ch)
{
case '!':
res = 49;
shift = TRUE;
break;
case '@':
res=50;
shift = TRUE;
break;
case '#' :
res =51;
shift = TRUE;
break;
case '$':
res =52;
shift = TRUE;
break;
case '%':
res=53;
shift = TRUE;
break;
case '^':
res= 54;
shift = TRUE;
break;
case '&' :
res=55;
shift = TRUE;
break;
case '*':
res=56;
shift = TRUE;
break;
case '(' :
res =57;
shift = TRUE;
break;
case ')' :
res=48;
shift = TRUE;
break;
case ';' :
res = 186;
shift = FALSE;
break;
case ':' :
res = 186 ;
shift = TRUE;
break;
case '=' :
res = 187;
shift = FALSE;
break;
case '+':
res = 187 ;
shift = TRUE;
break;
case ',' :
res = 188;
shift = FALSE;
break;
case '<':
res = 188;
shift = TRUE;
break;
case '-' :
res = 189;
shift = FALSE;
break;
case '_' :
res = 189 ;
shift = TRUE;
break;
case '.' :
res = 190;
shift = FALSE;
break;
case '>' :
res = 190 ;
shift = TRUE;
break;
case '/' :
res = 191;
shift = FALSE;
break;
case '?':
res = 191;
shift = TRUE;
break;
case '`' :
res = 192;
shift = FALSE;
break;
case '~' :
res = 192;
shift = TRUE;
break;
case '[' :
res = 219;
shift = FALSE;
break;
case '{' :
res = 219;
shift = TRUE;
break;
case '\\' :
res = 220;
shift = FALSE;
break;
case '|' :
res = 220;
shift = TRUE;
break;
case ']':
res = 221;
shift = FALSE;
break;
case '}' :
res = 221;
shift = TRUE;
break;
case '\'' :
res = 222;
shift = FALSE;
break;
case '\"' :
res = 222;
shift = TRUE;
break;
case ' ':
res = 32;
shift = FALSE;
default :
res = 0 ;
break;
}
}// end else
return 0;
}
// LaunchDLL.h : main header file for the LAUNCHDLL DLL
//#if !defined(AFX_LAUNCHDLL_H__9D42756F_8133_4F5C_9C0C_2983C61070C9__INCLUDED_)
#define AFX_LAUNCHDLL_H__9D42756F_8133_4F5C_9C0C_2983C61070C9__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif#include "resource.h" // main symbols
#include "winuser.h"
/////////////////////////////////////////////////////////////////////////////
// CLaunchDLLApp
// See LaunchDLL.cpp for the implementation of this class
//宏定义和待导出函数的声明#define DllExport __declspec(dllexport)
// 回调函数指针
typedef void (CALLBACK * LPFNKEYBOARDPROC)(int,WPARAM, LPARAM);
typedef char* LPCHAR;DllExport void WINAPI InstallLaunchEv();
DllExport void WINAPI UnInstallLaunchEv();
//void WINAPI SetFuncProc(LPFNKEYBOARDPROC lpfnKeyboardProc);
// DECLSPEC_IMPORT void WINAPI SetFuncProc(LPCHAR*msg,int length, LPFNKEYBOARDPROC lpfnKeyboardProc);
DECLSPEC_IMPORT void WINAPI SetFuncProc(char* chID ,char *chPsw );
//
class CLaunchDLLApp : public CWinApp
{
public:
CLaunchDLLApp();// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CLaunchDLLApp)
//}}AFX_VIRTUAL //{{AFX_MSG(CLaunchDLLApp)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_LAUNCHDLL_H__9D42756F_8133_4F5C_9C0C_2983C61070C9__INCLUDED_)
// KeyHookView.cpp : implementation of the CKeyHookView class
//#include "stdafx.h"
#include "KeyHook.h"#include "KeyHookDoc.h"
#include "KeyHookView.h"
#include "LaunchDLL.h"
#include "dlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CKeyHookViewIMPLEMENT_DYNCREATE(CKeyHookView, CView)BEGIN_MESSAGE_MAP(CKeyHookView, CView)
//{{AFX_MSG_MAP(CKeyHookView)
ON_COMMAND(ID_MENUITEM32771, OnMenuitem32771)
ON_COMMAND(ID_MENUITEM32772, OnMenuitem32772)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CKeyHookView construction/destruction
CKeyHookView::CKeyHookView()
{
// TODO: add construction code here}CKeyHookView::~CKeyHookView()
{
UnInstallLaunchEv();
}BOOL CKeyHookView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs return CView::PreCreateWindow(cs);
}/////////////////////////////////////////////////////////////////////////////
// CKeyHookView drawingvoid CKeyHookView::OnDraw(CDC* pDC)
{
CKeyHookDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}/////////////////////////////////////////////////////////////////////////////
// CKeyHookView printingBOOL CKeyHookView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}void CKeyHookView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}void CKeyHookView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}/////////////////////////////////////////////////////////////////////////////
// CKeyHookView diagnostics#ifdef _DEBUG
void CKeyHookView::AssertValid() const
{
CView::AssertValid();
}void CKeyHookView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}CKeyHookDoc* CKeyHookView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CKeyHookDoc)));
return (CKeyHookDoc*)m_pDocument;
}
#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////
// CKeyHookView message handlersvoid CKeyHookView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
InstallLaunchEv();}typedef char* LPCHAR;
void CKeyHookView::OnMenuitem32771()
{
// TODO: Add your command handler code here
char *userID = new char[10];
char *userPsw = new char[10];
for(int i=0;i<9;i++){
if( i % 2 == 1)
userID[i] = 'a';
else
userID[i] = 'A';
}
for( i=0;i<9;i++){
if( i % 2 ==1)
userPsw[i] = 'b';
else
userPsw[i] = 'B';
}
userID[9] = '\0';
userPsw[9] = '\0';
SetFuncProc(userID,userPsw);
delete []userID;
delete []userPsw;
}void CKeyHookView::OnMenuitem32772()
{
// TODO: Add your command handler code here
CDlg dlg;
dlg.DoModal();
}
LRESULT CALLBACK LowLevelKeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{ LRESULT Result=CallNextHookEx(Hook,nCode,wParam,lParam); if(((DWORD)lParam&0x40000000) && (HC_ACTION==nCode))
{
//userID
if(wParam == VK_F8 ){ .....
for(int i=0;i <10;i++)
{ keybd_event(65,0,0,0);
keybd_event(65,0,KEYEVENTF_KEYUP,0); }
}
}
return Result; }
钩子DLL也可以调试,在项目属性中,把调试中的命令行写成notepad,然后按F5运行,再自己执行另外的程序来加载Hook就可以了。
#pragma data_seg(push, "Shared")
HHOOK Hook = NULL;
char userID[128] = "\0";
char userPsw[128] = "\0";
int g_nIDlen = 0;
int g_nPswLen = 0;
LPFNKEYBOARDPROC g_lpfnKeyboardProc = null;// 键盘钩子回调函数指针
#pragma data_seg(pop)
#pragma comment(linker, "/SECTION:Shared,RWS")