EVC编程点滴四 - 钩子

wince下支持三种钩子:

1#define WH_JOURNALRECORD 0使应用程序可以监视输入事件。典型地,应用程序使用该HOOK记录鼠标、键盘输入事件以供以后回放。该HOOK是全局HOOK,并且不能在指定线程中使用。

2#define WH_JOURNALPLAYBACK 1使应用程序可以向系统消息队列中插入消息。该HOOK可以回放以前由WH_JOURNALRECORD HOOK录制的鼠标、键盘输入事件。在WH_JOURNALPLAYBACK Hook安装到系统时,鼠标、键盘输入事件将被屏蔽。该HOOK同样是一个全局HOOK,不能在指定线程中使用。

WH_JOURNALPLAYBACK Hook返回一个时间暂停值它告诉系统在处理当前回放的消息时系统等待百分之几秒。这使得此HOOK可以控制在回放时的时间事件

3#define WH_KEYBOARD_LL 20  

 

其中最常用的是键盘钩子,其它两个偶没有用过。

1.  设置钩子
通过SetWindowsHookEx ()函数

2.  释放钩子
UnhookWindowsHookEx()函数

3.  钩子进程
函数HookProc

4.  调用下一个钩子函数
CallNexHookEx()函数

 

钩子的建立

1.  建立一个动态连接库的.cpp文件。

// KeyBoardHook.cpp : Defines the entry point for the DLL application.

//

 

#include "stdafx.h"

#include "KeyBoardHook.h"

#include

#include "BasalMessage.h"

//#include "FileManage.h"

 

//告诉编译器将变量放入它自己的数据共享节中

#pragma data_seg("KeyHookData")

HINSTANCE hInst = NULL;

#pragma data_seg()

 

//告诉编译器设置共享节的访问方式为:读,写,共享

#pragma comment(linker, "/SECTION:KeyHookData,RWS")

 

 

BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call,

                       LPVOID lpReserved

                              )

{

    switch (ul_reason_for_call)

{

        case DLL_PROCESS_ATTACH:

               hInst = (HINSTANCE)hModule;

               break;

        case DLL_THREAD_ATTACH:

        case DLL_THREAD_DETACH:

        case DLL_PROCESS_DETACH:

               break;

    }

    return TRUE;

}

 

 

// This is an example of an exported variable

KEYBOARDHOOK_API int nKeyBoardHook=0;

 

// This is an example of an exported function.

KEYBOARDHOOK_API int fnKeyBoardHook(void)

{

return 42;

}

 

// This is the constructor of a class that has been exported.

// see KeyBoardHook.h for the class definition

CKeyBoardHook::CKeyBoardHook()

{

return;

}

 

 

extern "C" KEYBOARDHOOK_API void InstallHook(void)

{

if (hInst)

{

        hKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyBoardProc, hInst, 0);

}

}

 

extern "C" KEYBOARDHOOK_API void UnHook(void)

{

if (hKeyHook)

{

        UnhookWindowsHookEx(hKeyHook);

        hKeyHook = NULL;

}

 

hInst = NULL;

}

 

extern "C" KEYBOARDHOOK_API LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam)

{

TCHAR t_WndClassName[50] = { 0 };

HWND hCurActiveWnd = NULL;

HWND hCurForegroundWnd = NULL;

BOOL bIsTaskBarMsg = FALSE;

BOOL bIsOEMmsg = FALSE;

 

PKBDLLHOOKSTRUCT pkbhs = (PKBDLLHOOKSTRUCT)lParam;

 

if (WM_KEYDOWN == wParam)

{

        uCount++;

        RETAILMSG(1, (TEXT("WM_KEYDOWN vk %d /r/n"),pkbhs->vkCode));

        //响应按键声,并限制需要向上PostvkCode

        switch (pkbhs->vkCode)

        {

        case VK_UP:

               break;

        case VK_DOWN:

               break;

        case VK_LEFT:

               break;

        case VK_RIGHT:

               break;

        case VK_OEM_SELECT:

               bIsOEMmsg = TRUE;

               break;

        case VK_OEM_OK:

               bIsOEMmsg = TRUE;

               break;

        case VK_OEM_BACK:

               bIsOEMmsg = TRUE;

               break;

        case VK_OEM_DIAL:

               bIsOEMmsg = TRUE;

               break;

        case VK_NUMPAD1:

case 0x31:

               break;

        case VK_NUMPAD2:

case 0x32:

               break;

        case VK_NUMPAD3:

case 0x33:

               break;

        case VK_NUMPAD4:

case 0x34:

              break;

        case VK_NUMPAD5:

case 0x35:

               break;

        case VK_NUMPAD6:

case 0x36:

               break;

        case VK_NUMPAD7:

case 0x37:

               break;

        case VK_NUMPAD8:

case 0x38:

               break;

        case VK_NUMPAD9:

case 0x39:

               break;

        case VK_NUMPAD0:

case 0x30:

               break;

        case VK_OEM_ASTERISK:

               bIsOEMmsg = TRUE;

               break;

        case VK_OEM_POUND:

               bIsOEMmsg = TRUE;

               break;

        case VK_OEM_SIDEUP:

               bIsOEMmsg = TRUE;

               break;

        case VK_OEM_SIDEDOWN:

               bIsOEMmsg = TRUE;

               break;

        case VK_OEM_CAMERA:

               bIsOEMmsg = TRUE;

               break;

        default:

               uCount = 0;

               return CallNextHookEx(hKeyHook, nCode, wParam, lParam);    //继续传递消息

        }

 

        if (bNeedPassOnceMsg)

        {

               return TRUE;

        }

 

        //只发送OEM消息,其它消息并不拦截。

        //拦截原消息,发送自定义消息。

        //限制需要向上PostvkCode

        switch (pkbhs->vkCode)

        {

                      return CallNextHookEx(hKeyHook, nCode, wParam, (LPARAM)pkbhs);   //转换为回车消息传递(未测试)

}

        case VK_OEM_OK:

        case VK_OEM_BACK:

        case VK_OEM_DIAL:

        case VK_OEM_DISCONNECT:

               bIsOEMmsg = TRUE;

               break;

        case VK_NUMPAD1:

        case VK_NUMPAD2:

        case VK_NUMPAD3:

        case VK_NUMPAD4:

        case VK_NUMPAD5:

       case VK_NUMPAD6:

        case VK_NUMPAD7:

        case VK_NUMPAD8:

        case VK_NUMPAD9:

        case VK_NUMPAD0:

case 0x30:

case 0x31:

case 0x32:

case 0x33:

case 0x34:

case 0x35:

case 0x36:

case 0x37:

case 0x38:

case 0x39:

               break;

        case VK_OEM_ASTERISK:

        case VK_OEM_POUND:

        case VK_OEM_SIDEUP:

        case VK_OEM_SIDEDOWN:

        case VK_OEM_CAMERA:

               bIsOEMmsg = TRUE;

               break;

        default:

               return CallNextHookEx(hKeyHook, nCode, wParam, lParam);    //继续传递消息

        }

 

        //只发送OEM消息,其它消息并不拦截。

        if (bOnlySendOEMMsg)

        {

               if (bIsOEMmsg)

               {

                      PostMessage(hTopWnd, WM_USER_KEYUP, (WPARAM)(pkbhs->vkCode), (LPARAM)uCount);

                      return TRUE;  //拦截OEM消息,不再向上传递此消息。                    

               }

               else

               {

                      return CallNextHookEx(hKeyHook, nCode, wParam, lParam);    //继续传递其它消息

               }

        }

 

        //拦截原消息,发送自定义消息。

        if (bHoldUpMsg)

        {//菜单未弹出的情况

               PostMessage(hTopWnd, WM_USER_KEYUP, (WPARAM)(pkbhs->vkCode), 0L);

               return TRUE;  //拦截消息,不再向上传递此消息。

        }

}

else

{

        uCount = 0;

}

 

return CallNextHookEx(hKeyHook, nCode, wParam, lParam);    //继续传递消息

}

 

extern "C" KEYBOARDHOOK_API void SetAppHWND(HWND hCurAppWnd)

{

hAppWnd = hCurAppWnd;

}

 

extern "C" KEYBOARDHOOK_API void SetTopHWND(HWND hCurTopWnd)

{

hTopWnd = hCurTopWnd;

}

 

extern "C" KEYBOARDHOOK_API void SetHoldUpMsg(BOOL bHoldUp)

{

bHoldUpMsg = bHoldUp;

}

 

extern "C" KEYBOARDHOOK_API void SetOnlySendOEMMsg(BOOL bOnlySendOEM)

{

bOnlySendOEMMsg = bOnlySendOEM;

}

 

extern "C" KEYBOARDHOOK_API void SetNeedPassOnceMsg(BOOL bWhetherNeed)

{

bNeedPassOnceMsg = bWhetherNeed;

}

2.  建立头文件

 

// The following ifdef block is the standard way of creating macros which make exporting

// from a DLL simpler. All files within this DLL are compiled with the KEYBOARDHOOK_EXPORTS

// symbol defined on the command line. this symbol should not be defined on any project

// that uses this DLL. This way any other project whose source files include this file see

// KEYBOARDHOOK_API functions as being imported from a DLL, wheras this DLL sees symbols

// defined with this macro as being exported.

#ifdef KEYBOARDHOOK_EXPORTS

#define KEYBOARDHOOK_API __declspec(dllexport)

#else

#define KEYBOARDHOOK_API __declspec(dllimport)

#endif

 

// This class is exported from the KeyBoardHook.dll

class KEYBOARDHOOK_API CKeyBoardHook {

public:

CKeyBoardHook(void);

// TODO: add your methods here.

};

 

extern KEYBOARDHOOK_API int nKeyBoardHook;

 

KEYBOARDHOOK_API int fnKeyBoardHook(void);

 

extern "C" KEYBOARDHOOK_API void InstallHook(void);

extern "C" KEYBOARDHOOK_API void UnHook(void);

extern "C" KEYBOARDHOOK_API LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam);

extern "C" KEYBOARDHOOK_API void SetAppHWND(HWND hCurAppWnd);

extern "C" KEYBOARDHOOK_API void SetTopHWND(HWND hCurTopWnd);

extern "C" KEYBOARDHOOK_API void SetHoldUpMsg(BOOL bHoldUp);

extern "C" KEYBOARDHOOK_API void SetOnlySendOEMMsg(BOOL bOnlySendOEM);

extern "C" KEYBOARDHOOK_API void SetNeedPassOnceMsg(BOOL bWhetherNeed);

3.  建立程序主文件

if (hModule)

    {

        InHook = (pInstallHook)GetProcAddress(hModule, L"InstallHook");

        UnHook = (pUnHook)GetProcAddress(hModule, L"UnHook");

        SetAppHWND = (pSetAppHWND)GetProcAddress(hModule, L"SetAppHWND");

        SetTopHWND = (pSetTopHWND)GetProcAddress(hModule, L"SetTopHWND");

        SetHoldUpMsg = (pSetHoldUpMsg)GetProcAddress(hModule, L"SetHoldUpMsg");

        SetOnlySendOEMMsg = (pSetOnlySendOEMMsg)GetProcAddress(hModule, L"SetOnlySendOEMMsg");

        SetNeedPassOnceMsg = (pSetNeedPassOnceMsg)GetProcAddress(hModule, L"SetNeedPassOnceMsg");

 

        if (!InHook || !UnHook || !SetAppHWND || !SetTopHWND || !SetHoldUpMsg || !SetOnlySendOEMMsg || !SetNeedPassOnceMsg)

        {

            MessageBoxEx(hWnd, L"KeyboardHook.dll加载失败,程序被终止。", L"Info", MB_OK);

            PostQuitMessage(0);

        }

    }

    else

    {

        MessageBoxEx(hWnd, L"KeyboardHook.dll加载失败,程序被终止。", L"Info", MB_OK);

        PostQuitMessage(0);

    }

 

InHook();

 

 

DLL的编写,也可以参考以下网址中的内容:

http://www.bc-cn.net/Article/kfyy/cyy/jszl/200709/6328_2.html

 

你可能感兴趣的:(EVC4,编程)