在需要用到SOFT1和SOFT2两个按键的时候, 也尝试了各种方案, 最后还是选个钩子函数, 但是在使用的过程中还是出现了一些问题的, 一些解决了一些还没有。下面有以下网上很多的实现。 且看这个
winceKBhook.h
#ifndef _WINCE_KB_HOOK_H #define _WINCE_KB_HOOK_H //used for passing to SetWindowsHookEx funtion to set a Low level (LL) keyboard hook #define WH_KEYBOARD_LL 20 // Define the function types used by hooks typedef LRESULT (CALLBACK* HOOKPROC)(int code, WPARAM wParam, LPARAM lParam); typedef HHOOK (WINAPI *_SetWindowsHookExW)(int, HOOKPROC, HINSTANCE, DWORD); typedef LRESULT (WINAPI *_CallNextHookEx)(HHOOK, int, WPARAM, LPARAM); typedef LRESULT (WINAPI *_UnhookWindowsHookEx)(HHOOK); // For the low level keyboard hook, your keyboards procedures is passed a pointer to KBDLLHOOKSTRUCT instance typedef struct { DWORD vkCode; DWORD scanCode; DWORD flags; DWORD time; ULONG_PTR dwExtraInfo; } KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT; // Win32 Hook APIs static _SetWindowsHookExW SetWindowsHookEx; static _UnhookWindowsHookEx UnhookWindowsHookEx; static _CallNextHookEx CallNextHookEx; bool ActivateKBHook(HINSTANCE hInstance, HOOKPROC LLKeyboardHookCallbackFunction); bool DeactivateKBHook(); HRESULT DefHookProc(int, WPARAM, LPARAM); #endif
winceKBhook.cpp
#include "stdafx.h" #include "winceKBhook.h" //globals HINSTANCE g_hHookApiDLL = NULL; //handle to coredll.dll, where all the hook related APIs are present HHOOK g_hInstalledLLKBDhook = NULL; //g_hInstalledLLKBDhook represents handle to the installed KB hook bool ActivateKBHook(HINSTANCE hInstance, HOOKPROC LLKeyboardHookCallbackFunction) { //we need to manually load these standard Win32 API calls //MSDN states that these aren't supported in WinCE SetWindowsHookEx = NULL; CallNextHookEx = NULL; UnhookWindowsHookEx = NULL; //now load the coredll.dll g_hHookApiDLL = LoadLibrary(_T("coredll.dll")); if(g_hHookApiDLL == NULL) { //something is awfully wrong //the dll has to be present return false; } else { //load the SetWindowsHookEx API call //the SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. //You would install a hook procedure to monitor the system for certain types of events. //here we use use the hook to monitor kyeboard events SetWindowsHookEx = (_SetWindowsHookExW)GetProcAddress(g_hHookApiDLL, _T("SetWindowsHookExW")); if(SetWindowsHookEx == NULL) { //this means that MS has really stopped supporting this API in WinCE return false; } else { //install the KB hook //the hande needs to be saved for default processing of the events and to uninstall the hook, once we are done with it g_hInstalledLLKBDhook = SetWindowsHookEx(WH_KEYBOARD_LL, LLKeyboardHookCallbackFunction, hInstance, 0); if(g_hInstalledLLKBDhook == NULL) { return false; } } //load CallNextHookEx() API call //the CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain. //we use this call for default processing of events. CallNextHookEx = (_CallNextHookEx)GetProcAddress(g_hHookApiDLL, _T("CallNextHookEx")); if(CallNextHookEx == NULL) { return false; } //load UnhookWindowsHookEx() API //the UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx function. //we use this call to unistall the hook. UnhookWindowsHookEx = (_UnhookWindowsHookEx)GetProcAddress(g_hHookApiDLL, _T("UnhookWindowsHookEx")); if(UnhookWindowsHookEx == NULL) { return false; } } //all the APIs are loaded and the application is hooked return true; } bool DeactivateKBHook() { //unload the hook if(g_hInstalledLLKBDhook != NULL) { UnhookWindowsHookEx(g_hInstalledLLKBDhook); g_hInstalledLLKBDhook = NULL; } //unload the coredll.dll if(g_hHookApiDLL != NULL) { FreeLibrary(g_hHookApiDLL); g_hHookApiDLL = NULL; } //we have terminated gracefully return true; } HRESULT DefHookProc(int nCode, WPARAM wParam, LPARAM lParam) { return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam); }
这个类似的实现网上一抄一大把。 我也搞了一个来实现, 还搞了一个DefHookProc函数, 因为懒得把CallNextHookEx时候要用的HHOOK公开了,所以一样的, hook filter里面就调用DefHookProc就好, 不需要调用CallNextHookEx了,一个参数我帮忙填写好了。
末了, 我尝试的实现了一下filter 函数:
int BlockKeyList[] = {VK_F1,VK_F2}; #ifndef HC_ACTION #define HC_ACTION 0 #endif //HC_ACTION LRESULT CALLBACK LLKeyboardHookCallbackFunction(int nCode, WPARAM wParam, LPARAM lParam) { KBDLLHOOKSTRUCT* pHook = (KBDLLHOOKSTRUCT*)lParam; if(nCode >= HC_ACTION) { if( wParam == WM_KEYDOWN && pHook->vkCode == VK_F1) { g_App.onKeyEvent(KEY_EVENT_KEY_PRESS, SL_KEY_SOFT1, lParam); return 1; } else if (wParam == WM_KEYUP && pHook->vkCode == VK_F1) { g_App.onKeyEvent(KEY_EVENT_KEY_RELEASE, SL_KEY_SOFT1, lParam); return 1; } else if (wParam == WM_KEYDOWN && pHook->vkCode == VK_F2) { g_App.onKeyEvent(KEY_EVENT_KEY_PRESS, SL_KEY_SOFT2, lParam); return 1; } else if (wParam == WM_KEYUP && pHook->vkCode == VK_F2) { g_App.onKeyEvent(KEY_EVENT_KEY_RELEASE, SL_KEY_SOFT2, lParam); return 1; } } return CallNextHookEx(g_hInstalledLLKBDhook, nCode, wParam, lParam); }
自 己看了应该没有什么问题, 但是实际上跑的是时候发现几次都crash了。 当然这些crash都和Messagebox有关系, 都是弹出Messagebox的时候就程序再没有响应了!!! 糊涂了,难道是messagebox是不同的线程¥%¥……%, 想来想去还是至少有点, g_App.onKeyEvent如果里面弹出Messagebox这里岂不是阻塞了?? 可能这样的函数是不允许你阻塞在这里的。 所以决定改了, 用PostMessage发个异步的消息看看。
if (code >= 0) { HWND hWnd; TCHAR szTitle[MAX_LOADSTRING]; // title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // main window class name LoadString(g_hInst, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(g_hInst, IDC_SCANLIFE, szWindowClass, MAX_LOADSTRING); //If it is already running, then focus on the window, and exit hWnd = FindWindow(szWindowClass, szTitle); if (hWnd) { if (pHook->vkCode == VK_F1 && wParam == WM_KEYDOWN) { PostMessage(hWnd, WM_KEYDOWN, VK_F1, 0); return true; } else if (pHook->vkCode == VK_F1 && wParam == WM_KEYUP) { PostMessage(hWnd, WM_KEYUP, VK_F1, 0); return true; } else if (pHook->vkCode == VK_F2 && wParam == WM_KEYDOWN) { PostMessage(hWnd, WM_KEYDOWN, VK_F2, 0); return true; } else if (pHook->vkCode == VK_F2 && wParam == WM_KEYUP) { PostMessage(hWnd, WM_KEYUP, VK_F2, 0); return true; } } } return DefHookProc(code, wParam, lParam);
果然一把通过了:) 当然就像开始就说的一样, 还是有问题没有解决, 在Smartphone上有的手机直接SetWindowsHookEx失败! 这个除了程序签名估计没有什么办法。 anyway 继续探索吧。