下文是参考
http://blog.csdn.net/jayky/archive/2006/11/16/1388212.aspx
而改写的。。。
钩取输入法的例子
最近用键盘钩子截获字符输入时是截不到特殊字符的,比方说中文输入法之类的.后来用到了消息钩子去HOOK WM_IME_CHAR,这时候大部分已经能够获取了,但是对于其他一些程序,比方说WORD之类的也就不能截获了.后来到MSDN上查到, 要用到WM_IME_COMPOSITION消息,并且在处理该消息时要用到IMM的一些库函数从输入法数据区中获取.比方说ImmGetContext,ImmGetCompositionString等等.
以下是源代码:
#define HC_IME_COPYDATA WM_USER+100
#define SH_IMMMESSAGE -3
HookProc UserMouseHookCallback = NULL;
HookProc UserKeyboardHookCallback = NULL;
HookProc UseImeMessageHookCallback = NULL;
HookProc SystemHookCallback = NULL;
HHOOK hookMouse = NULL;
HHOOK hookKeyboard = NULL;
HHOOK hookImeMessage = NULL;
HHOOK hookSystem = NULL;
//
// Store the application instance of this module to pass to
// hook initialization. This is set in DLLMain().
//
HINSTANCE g_appInstance = NULL;
MessageFilter mouseFilter;
MessageFilter keyboardFilter;
MessageFilter imeFilter;
static LRESULT CALLBACK InternalKeyboardHookCallback(int code, WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK InternalMouseHookCallback(int code, WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK InternalImeMessageHookCallback(int code, WPARAM wparam, LPARAM lparam);
// 仅内部用
static LRESULT CALLBACK privateImeMessageHookCallback(int code, WPARAM wparam, LPARAM lparam);
extern HINSTANCE g_appInstance;
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
//
// Capture the application instance of this module to pass to
// hook initialization.
//
if (g_appInstance == NULL)
{
g_appInstance = hinstDLL;
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
OutputDebugString("Not sure what just happened./n");
break;
}
return TRUE;
}
static HANDLE SetSystemHookHandler()
{
// 在当前进程做一个局部钩子接受其它进程钩子发来的消息
HANDLE hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,"SystemHookHandler");
if (hMap == NULL)
{
hMap = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,1024,"SystemHookHandler");
}
LPVOID lpMapAddr = MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS, 0,0,0);
DWORD tid = GetCurrentThreadId();//GetCurrentProcessId();
char data[50];
sprintf(data,"%ul",tid);
memcpy(lpMapAddr,data,strlen(data));
FlushViewOfFile(lpMapAddr,strlen(data)+1);
UnmapViewOfFile(hMap);
return hMap;
}
static DWORD GetSystemHookHandler()
{
HANDLE hMap = OpenFileMapping(FILE_MAP_READ, 0, "SystemHookHandler");
if (hMap == NULL)return NULL;
LPVOID lpMapAddr = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
DWORD tid = atol((char*)lpMapAddr);
UnmapViewOfFile(hMap);
return tid;
}
int SetUserHookCallback(HookProc userProc, UINT hookID)
{
if (userProc == NULL)
{
return HookCoreErrors::SetCallBack::ARGUMENT_ERROR;
}
if (hookID == WH_KEYBOARD_LL)//键盘
{
if (UserKeyboardHookCallback != NULL)
{
return HookCoreErrors::SetCallBack::ALREADY_SET;
}
UserKeyboardHookCallback = userProc;
keyboardFilter.Clear();
return HookCoreErrors::SetCallBack::SUCCESS;
}
else if (hookID == WH_MOUSE_LL)//鼠标
{
if (UserMouseHookCallback != NULL)
{
return HookCoreErrors::SetCallBack::ALREADY_SET;
}
UserMouseHookCallback = userProc;
mouseFilter.Clear();
return HookCoreErrors::SetCallBack::SUCCESS;
}
else if (hookID == SH_IMMMESSAGE)//输入法
{
if (UseImeMessageHookCallback != NULL)
{
return HookCoreErrors::SetCallBack::ALREADY_SET;
}
if (SetSystemHookHandler() == NULL)
{
return HookCoreErrors::SetCallBack::HANDLE_ERROR;
}
hookSystem = SetWindowsHookEx(3, (HOOKPROC)privateImeMessageHookCallback, g_appInstance, 0);
if (hookSystem != NULL)
{
UseImeMessageHookCallback = userProc;
imeFilter.Clear();
return HookCoreErrors::SetCallBack::SUCCESS;
}
return HookCoreErrors::SetCallBack::HANDLE_ERROR;
}
return HookCoreErrors::SetCallBack::NOT_IMPLEMENTED;
}
bool InitializeHook(UINT hookID, int threadID)
{
if (g_appInstance == NULL)
{
return false;
}
if (hookID == WH_KEYBOARD_LL)
{
if (UserKeyboardHookCallback == NULL)
{
return false;
}
hookKeyboard = SetWindowsHookEx(hookID, (HOOKPROC)InternalKeyboardHookCallback, g_appInstance, threadID);
return hookKeyboard != NULL;
}
else if (hookID == WH_MOUSE_LL)
{
if (UserMouseHookCallback == NULL)
{
return false;
}
hookMouse = SetWindowsHookEx(hookID, (HOOKPROC)InternalMouseHookCallback, g_appInstance, threadID);
return hookMouse != NULL;
}
else if (hookID == SH_IMMMESSAGE)
{
if (UseImeMessageHookCallback == NULL)
{
return false;
}
hookImeMessage = SetWindowsHookEx(3, (HOOKPROC)InternalImeMessageHookCallback, g_appInstance, threadID);
return hookImeMessage != NULL;
}
return false;
}
void UninitializeHook(UINT hookID)
{
if (hookID == WH_KEYBOARD_LL)
{
if (hookKeyboard != NULL)
{
UnhookWindowsHookEx(hookKeyboard);
}
hookKeyboard = NULL;
}
else if (hookID == WH_MOUSE_LL)
{
if (hookMouse != NULL)
{
UnhookWindowsHookEx(hookMouse);
}
hookMouse = NULL;
}
else if (hookID == SH_IMMMESSAGE)
{
if (hookImeMessage != NULL)
{
UnhookWindowsHookEx(hookImeMessage);
}
hookImeMessage = NULL;
}
}
void Dispose(UINT hookID)
{
if (hookID == WH_KEYBOARD_LL)
{
UserKeyboardHookCallback = NULL;
}
else if (hookID == WH_MOUSE_LL)
{
UserMouseHookCallback = NULL;
}
else if (hookID == SH_IMMMESSAGE)
{
UseImeMessageHookCallback = NULL;
// 关闭内部的消息循环
if (hookSystem != NULL)
{
UnhookWindowsHookEx(hookSystem);
}
hookSystem = NULL;
}
}
int FilterMessage(UINT hookID, int message)
{
if (hookID == WH_KEYBOARD_LL)
{
if (keyboardFilter.AddMessage(message))
{
return HookCoreErrors::FilterMessage::SUCCESS;
}
else
{
return HookCoreErrors::FilterMessage::FAILED;
}
}
else if (hookID == WH_MOUSE_LL)
{
if(mouseFilter.AddMessage(message))
{
return HookCoreErrors::FilterMessage::SUCCESS;
}
else
{
return HookCoreErrors::FilterMessage::FAILED;
}
}
else if (hookID == SH_IMMMESSAGE)
{
if(imeFilter.AddMessage(message))
{
return HookCoreErrors::FilterMessage::SUCCESS;
}
else
{
return HookCoreErrors::FilterMessage::FAILED;
}
}
return HookCoreErrors::FilterMessage::NOT_IMPLEMENTED;
}
static LRESULT CALLBACK InternalMouseHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
if (code < 0)
{
return CallNextHookEx(hookMouse, code, wparam, lparam);
}
if (UserMouseHookCallback != NULL && !mouseFilter.IsFiltered((int)wparam))
{
UserMouseHookCallback(code, wparam, lparam);
}
return CallNextHookEx(hookMouse, code, wparam, lparam);
}
static LRESULT CALLBACK InternalKeyboardHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
if (code < 0)
{
return CallNextHookEx(hookKeyboard, code, wparam, lparam);
}
if (UserKeyboardHookCallback != NULL && !keyboardFilter.IsFiltered((int)wparam))
{
UserKeyboardHookCallback(code, wparam, lparam);
}
return CallNextHookEx(hookKeyboard, code, wparam, lparam);
}
static void IntenralGetMessageReading(LPTSTR msg)
{
HANDLE m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,"InternalImeMessageHookCallback");
if (m_hMapFile != NULL)
{
LPTSTR lpMapAddr = (LPTSTR)MapViewOfFile(m_hMapFile,FILE_MAP_ALL_ACCESS,0,0,0);
return;
}
}
static bool isProcess = false;
static LRESULT CALLBACK InternalImeMessageHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
if (code < 0)
{
return CallNextHookEx(hookImeMessage, code, wparam, lparam);
}
PMSG pmsg = (PMSG)lparam;
if (pmsg->message == WM_KEYUP && isProcess)
{
//if(pmsg->wParam == VK_SPACE || pmsg->wParam == VK_RETURN){
// 强制false,
// 否则有可能在接下来的无WM_KEYDOWN消息情况下产生WM_KEYUP
isProcess = false;
// 发送给处理进程处理消息
DWORD tid = GetSystemHookHandler();
if (tid != NULL)
{
HIMC hIMC;
HWND hWnd=pmsg->hwnd;
DWORD dwSize;
char lpstr[20];
//先获取当前正在输入的窗口的输入法句柄
hIMC = ImmGetContext(hWnd);
// 先将ImmGetCompositionString的获取长度设为0来获取字符串大小.
dwSize = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0);
// 缓冲区大小要加上字符串的NULL结束符大小,
// 考虑到UNICODE
dwSize += sizeof(WCHAR);
memset(lpstr, 0, 20);
// 再调用一次.ImmGetCompositionString获取字符串
ImmGetCompositionString(hIMC, GCS_RESULTSTR, lpstr, dwSize);
// 现在lpstr里面即是输入的汉字了。你可以处理lpstr,当然也可以保存为文件...
bool isEmpty = true;
for(int i=0;i<20;i++)
{
if (lpstr[i] != '/0')
isEmpty = false;
}
if (!isEmpty)
{
// 保存在共享内存并返回指向共享内存的
HANDLE m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,"ImeMessage");
if (m_hMapFile == NULL)
{
//创建共享文件。
m_hMapFile = CreateFileMapping( (HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,20,"ImeMessage");
}
//拷贝数据到共享文件里。
LPTSTR lpMapAddr = (LPTSTR)MapViewOfFile(m_hMapFile,FILE_MAP_ALL_ACCESS,0,0,0);
memset(lpMapAddr,0,20);
memcpy(lpMapAddr, lpstr,strlen(lpstr));
FlushViewOfFile(lpMapAddr,strlen(lpstr)+1);
UnmapViewOfFile(m_hMapFile);
ImmReleaseContext(hWnd, hIMC);
// 通知接受
PostThreadMessage(tid,HC_IME_COPYDATA,(WPARAM)(&pmsg->hwnd),lparam);
}
}
//}
}
else if (pmsg->message == WM_KEYDOWN)
{
if(pmsg->wParam == VK_PROCESSKEY)
{
isProcess= true;
}
else
{
isProcess = false;
}
}
else if (pmsg->message == WM_CHAR && !isProcess)
{
//if(pmsg->wParam != VK_SPACE && pmsg->wParam != VK_RETURN){
// 发送给处理进程处理消息
DWORD tid = GetSystemHookHandler();
if (tid != NULL)
{
// 保存在共享内存并返回指向共享内存的
HANDLE m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,"ImeMessage");
if (m_hMapFile == NULL)
{
//创建共享文件。
m_hMapFile = CreateFileMapping( (HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,20,"ImeMessage");
}
//拷贝数据到共享文件里。
LPTSTR lpMapAddr = (LPTSTR)MapViewOfFile(m_hMapFile,FILE_MAP_ALL_ACCESS,0,0,0);
memset(lpMapAddr,0,20);
char lpstr[2];
lpstr[0] = (char)pmsg->wParam;
lpstr[1] = '/0';
memcpy(lpMapAddr, lpstr,strlen(lpstr));
FlushViewOfFile(lpMapAddr,strlen(lpstr)+1);
UnmapViewOfFile(m_hMapFile);
// 通知接受
PostThreadMessage(tid,HC_IME_COPYDATA,(WPARAM)(&pmsg->hwnd),lparam);
}
//}
}
return CallNextHookEx(hookImeMessage, code, wparam, lparam);
}
static int imeCount = 0;
static LRESULT CALLBACK privateImeMessageHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
if (code >= 0)
{
// 接受挂载进程发到当前进程上的消息
PMSG pmsg = (PMSG)lparam;
if (pmsg->message == HC_IME_COPYDATA)
{
if (imeCount % 2 != 0)
{
imeCount = 0;
}
else
{
imeCount++;
if (UseImeMessageHookCallback != NULL && !imeFilter.IsFiltered((int)wparam))
{
UseImeMessageHookCallback(code, pmsg->wParam, lparam);
}
}
}
}
return CallNextHookEx(hookImeMessage, code, wparam, lparam);
}