您当前的位置:首页 > 文章摘抄 > 正文

keyboardproc(什么是钩子函数钩子函数的使用)

本文目录

  • 什么是钩子函数钩子函数的使用
  • 如果当焦点处于其他应用程序时,如何拦截键盘事件
  • 键盘钩子无法屏蔽windows键昨天弄了一个晚上
  • MFC 禁用键盘或鼠标的程序
  • 关于LRESULT CALLBACK KeyboardProc的问题求教
  • VC中不用DLL在窗体中加入全局钩子
  • 回调函数到底是怎么回事
  • 键盘钩子怎么 使用
  • C++全局键盘勾子的问题

什么是钩子函数钩子函数的使用

WINDOWS的钩子函数可以认为是WINDOWS的主要特性之一。利用它们,您可以捕捉您自己进程或其它进程发生的事件。通过“钩挂”,您可以给WINDOWS一个处理或过滤事件的回调函数,该函数也叫做“钩子函数”,当每次发生您感兴趣的事件时,WINDOWS都将调用该函数。一共有两种类型的钩子:局部的和远程的。 局部钩子仅钩挂您自己进程的事件。 远程的钩子还可以将钩挂其它进程发生的事件。远程的钩子又有两种: 基于线程的 它将捕获其它进程中某一特定线程的事件。简言之,就是可以用来观察其它进程中的某一特定线程将发生的事件。 系统范围的 将捕捉系统中所有进程将发生的事件消息。 当您创建一个钩子时,WINDOWS会先在内存中创建一个数据结构,该数据结构包含了钩子的相关信息,然后把该结构体加到已经存在的钩子链表中去。新的钩子将加到老的前面。当一个事件发生时,如果您安装的是一个局部钩子,您进程中的钩子函数将被调用。如果是一个远程钩子,系统就必须把钩子函数插入到其它进程的地址空间,要做到这一点要求钩子函数必须在一个动态链接库中,所以如果您想要使用远程钩子,就必须把该钩子函数放到动态链接库中去。当然有两个例外:工作日志钩子和工作日志回放钩子。这两个钩子的钩子函数必须在安装钩子的线程中。原因是:这两个钩子是用来监控比较底层的硬件事件的,既然是记录和回放,所有的事件就当然都是有先后次序的。所以如果把回调函数放在DLL中,输入的事件被放在几个线程中记录,所以我们无法保证得到正确的次序。故解决的办法是:把钩子函数放到单个的线程中,譬如安装钩子的线程。 钩子一共有14种,以下是它们被调用的时机: WH_CALLWNDPROC 当调用SendMessage时 WH_CALLWNDPROCRET 当SendMessage的调用返回时 WH_GETMESSAGE 当调用GetMessage 或 PeekMessage时 WH_KEYBOARD 当调用GetMessage 或 PeekMessage 来从消息队列中查询WM_KEYUP 或 WM_KEYDOWN 消息时 WH_MOUSE 当调用GetMessage 或 PeekMessage 来从消息队列中查询鼠标事件消息时 WH_HARDWARE 当调用GetMessage 或 PeekMessage 来从消息队列种查询非鼠标、键盘消息时 WH_MSGFILTER 当对话框、菜单或滚动条要处理一个消息时。该钩子是局部的。它时为那些有自己的消息处理过程的控件对象设计的。 WH_SYSMSGFILTER 和WH_MSGFILTER一样,只不过是系统范围的 WH_JOURNALRECORD 当WINDOWS从硬件队列中获得消息时 WH_JOURNALPLAYBACK 当一个事件从系统的硬件输入队列中被请求时 WH_SHELL 当关于WINDOWS外壳事件发生时,譬如任务条需要重画它的按钮. WH_CBT 当基于计算机的训练(CBT)事件发生时 WH_FOREGROUNDIDLE 由WINDOWS自己使用,一般的应用程序很少使用 WH_DEBUG 用来给钩子函数除错 附:如何使用钩子函数(接收到字母A按下时,窗体由最小化弹出的完整的代码) Public Declare Function CallNextHookEx Lib “user32“ _ (ByVal hHook As Long, _ ByVal nCode As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long Public Declare Function UnhookWindowsHookEx Lib “user32“ _ (ByVal hHook As Long) As Long Public Declare Function SetWindowsHookEx Lib “user32“ _ Alias “SetWindowsHookExA“ _ (ByVal idHook As Long, _ ByVal lpfn As Long, _ ByVal hmod As Long, _ ByVal dwThreadId As Long) As Long Public Const WH_KEYBOARD = 2 Public Const KEY_WINSTART = 91 Public Const KEY_WINMENU = 93 Global hHook As Long Public Function KeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long If nCode 》= 0 Then If wParam = KEY_WINMENU Or wParam = KEY_WINSTART Then If (lParam And &HC0000000) = 0 Then MsgBox ““, , ““ KeyboardProc = 1 Exit Function End If End If End If KeyboardProc = CallNextHookEx(hHook, nCode, wParam, lParam) End Function Option Explicit Private Sub Command1_Click() form2.Show 1 End Sub Private Sub form_Load() hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf KeyboardProc, 0&, App.ThreadID) Me.Show End Sub Private Sub form_Unload(Cancel As Integer) Call UnhookWindowsHookEx(hHook) End Sub

如果当焦点处于其他应用程序时,如何拦截键盘事件

WINDOWS的消息处理机制为了能在应用程序中监控系统的各种事件消息,提供了挂接 各种反调函数(HOOK)的功能。这种挂钩函数(HOOK)类似扩充中断驱动程序,挂钩上 可以挂接多个反调函数构成一个挂接函数链。系统产生的各种消息首先被送到各种 挂接函数,挂接函数根据各自的功能对消息进行监视、修改和控制等,然后交还控 制权或将消息传递给下一个挂接函数以致最终达到窗口函数。WINDOW系统的这种反 调函数挂接方法虽然会略加影响到系统的运行效率,但在很多场合下是非常有用 的,通过合理有效地利用键盘事件的挂钩函数监控机制可以达到预想不到的良好效 果。一、在WINDOWS键盘事件上挂接监控函数的方法 WINDOW下可进行挂接的过滤函数包括11种: WH_CALLWNDPROC 窗口函数的过滤函数 WH_CBT 计算机培训过滤函数 WH_DEBUG 调试过滤函数 WH_GETMESSAGE 获取消息过滤函数 WH_HARDWARE 硬件消息过滤函数 WH_JOURNALPLAYBACK 消息重放过滤函数 WH_JOURNALRECORD 消息记录过滤函数 WH_MOUSE 鼠标过滤函数 WH_MSGFILTER 消息过滤函数 WH_SYSMSGFILTER 系统消息过滤函数 WH_KEYBOARD 键盘过滤函数其中键盘过滤函数是最常用最有用的过滤函数类型,不管是哪一种类型的过滤函 数,其挂接的基本方法都是相同的。 WINDOW调用挂接的反调函数时总是先调用挂接链首的那个函数,因此必须将键盘挂 钩函数利用函数SetWindowsHookEx()将其挂接在函数链首。至于消息是否传递给函 数链的下一个函数是由每个具体函数功能确定的,如果消息需要传统给下一个函 数,可调用API函数的CallNextHookEx()来实现,如果不传递直接返回即可。 挂接函数可以是用来监控所有线程消息的全局性函数,也可以是单独监控某一线程 的局部性函数。如果挂接函数是局部函数,可以将它放到一个.DLL动态链接库中, 也可以放在一个局部模块中;如果挂接函数是全局的,那么必须将其放在一个.DLL 动态链接库中。挂接函数必须严格按照下述格式进行声明,以键盘挂钩函数为例: int FAR PASCAL KeyboardProc( int nCode,WORD wParam,DWORD lParam) 其中KeyboardProc为定义挂接函数名,该函数必须在模块定义文件中利用EXPORTS命 令进行说明;nCode决定挂接函数是否对当前消息进行处理;wParam和lParam为具体 的消息内容。二、键盘事件挂接函数的安装与下载 在程序中可以利用函数SetWindowsHookEx()来挂接过滤函数,在挂接函数时必须指 出该挂接函数的类型、函数的入口地址以及函数是全局性的还是局部性的,挂接函 数的具体调用格式如下: SetWindowsHookEx(iType,iProc,hInst,iCode) 其中iType为挂接函数类型,键盘类型为WH_KEYBOARD,iProc为挂接函数地址,hInst 为挂接函数链接库实例句柄,iCode为监控代码-0表示全局性函数。 如果挂接函数需要将消息传递给下一个过滤函数,则在该挂接函数返回前还需要调 用一次CallNextHookEx()函数,当需要下载挂接函数时,只要调用一次 UnhookWindowsHookEx(iProc)函数即可实现。 如果函数是全局性的,那么它必须放在一个.DLL动态链接库中,这时该函数调用方 法可以和其它普通.DLL函数一样有三种: 1.在DEF定义文件中直接用函数名或序号说明: EXPORTS WEP @1 RESIDENTNAME InitHooksDll @2 InstallFilter @3 KeyboardProc @4 用序号说明格式为:链接库名.函数名(如本例中说明方法为KEYDLL.KeyboardProc)。 2.在应用程序中利用函数直接调用: 首先在应用程序中利用LoadLibrary(LPSTR “链接库名“)将动态链接库装入,并取得 装载库模块句柄hInst,然后直接利用GetProcAddress(HINSTANCE hInst,LPSTR “函 数过程名“)获取函数地址,然后直接调用该地址即可,程序结束前利用函数 FreeLibrary( )释放装入的动态链接库即可。 3.利用输入库.LIB方法 利用IMPLIB.EXE程序在建立动态链接库的同时建立相应的输入库.LIB,然后直接在 项目文件中增加该输入库。

键盘钩子无法屏蔽windows键昨天弄了一个晚上

应该用低级键盘钩子。我写了个示例程序,请下载。/* stdafx.h文件的开头#if _MSC_VER 》 1000#pragma once#endif // _MSC_VER 》 1000#define _WIN32_WINNT 0x0500 //在 stdafx.h中添加这一句#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers*//**************************************************************************** 低级键盘钩子****************************************************************************/HHOOK LowLevelKeyboardHook=NULL; //钩子句柄//低级键盘钩子LRESULT CALLBACK LowLevelKeyboardProc(int nCode,WPARAM wParam, LPARAM lParam){ if (nCode《0 ) return CallNextHookEx(LowLevelKeyboardHook,nCode,wParam,lParam); if (wParam==WM_KEYDOWN) { int KeyCode=((KBDLLHOOKSTRUCT *) lParam )-》vkCode; trace( KeyCode ); if ( KeyCode == 91 ) { trace(“You Press the Win Key“); return 1; } } return CallNextHookEx(LowLevelKeyboardHook,nCode,wParam,lParam); //传递钩子信息 } void CDemoDlg::OnButton1() { //start Low Level Keyboard hook LowLevelKeyboardHook=SetWindowsHookEx(WH_KEYBOARD_LL,LowLevelKeyboardProc,GetModuleHandle(NULL),0); ASSERT(LowLevelKeyboardHook);}void CDemoDlg::OnButton2() { //stop Low Level Keyboard hook VERIFY(UnhookWindowsHookEx(LowLevelKeyboardHook)); }

MFC 禁用键盘或鼠标的程序

实现这个功能,要写一个DLL(动态连接库),主要的功能是屏蔽键盘和鼠标,这里需要两个东西,一个是鼠标过程函数,另外的是键盘过程函数即LRESULTCALLBACKMouseProc(intnCode,WPARAMwParam,LPARAMlParam);和LRESULTCALLBACKKeyboardProc(intcode,WPARAMwParam,LPARAMlParam);因为你要实现的功能是屏蔽鼠标键盘,所以你只要让这两个函数返回TRUE就行,最好留个后门.然后就可以新建一个工程,在里面写主函数,来调用这个DLL,就可以实现你说的功能了;我自己写过这个,要的话我给你源码(记住生成DLL时也生成LIB文件,不要也行)

关于LRESULT CALLBACK KeyboardProc的问题求教

KeyboardProc 键盘钩子处理函数: 首先键盘钩子处理函数的函数名是可以自定义的 ,例如:MyKeyboardProc() 函数原型: LRESULT CALLBACK KeyboardProc( int code, WPARAM wParam, LPARAM lParam ); 参数: code: 根据这个数值决定怎样处理消息 如果code 小于0,则 必须让KeyboardProc()函数返回CallNextHookEx() code可以是下列值: HC_ACTION:wParam和lParam包含按键消息 HC_NOREMOVE:wParam和lParam包含按键消息,并且按键消息不能从消息队列中移除(一个被PeekMessage函数调用的请求,指定 PM_NOREMOVE标志) wParam: 按键的虚拟键值消息,例如:VK_F1 lParam: 32位内存,内容描述包括:指定扩展键值,扫描码,上下文,重复次数。 0-15位: 描述:按下键盘次数。 16-23位 指定扫描码. 依赖于OEM 24位 当24位为1时候:表示按键是扩展键 当24位为0时候:表示按键是是数字键盘按键 25-28位 保留位 29位 上下文键:为1时: ALT按下,其他情况为0 30位 如果是按键按下后发送的消息,30位为1,如果是按键抬起后30位为1; 31位 指定转变状态:31位为0时候,按键正在被按下,为1时候,按键正在被释放 返回值: 如果参数1:code小于0,则必须 返回CallNextHookEx(),也就是返回CallNextHookEx()的返回值 如果参数1:code大于等于0,并且钩子处理函数没有处理消息,强烈建议您 返回CallNextHookEx()的返回值,否则当您安装WH_KEYBOARD钩子时 ,钩子将不会得到通知,并返回错误结果。 如果钩子处理的消息,您可以返回一个非0值,防止系统把消息传递给钩子链中的下一个钩子,或者把消息发送到目标窗口。 备注: 安装键盘钩子需要把WH_KEYBOARD作为SetWindowsHookEx()的第一个参数,并且把键盘钩子处理函数的函数指针作为SetWindowsHookEx()的第2 个参数. 需求: 头文件:Declared in Winuser.h, include Windows.h 导入库:无 最小系统需求:Windows 95, Windows NT 3.1 相关: Hooks Overview, CallNextHookEx, GetMessage, PeekMessage, SetWindowsHookEx, WM_KEYUP, WM_KEYDOWN 附赠例子: //屏蔽所有键盘输入 //DLL项目中代码 //DLL.cpp #include 《windows.h》 LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam) { return 1; } _declspec(dllexport) void SetHook() { SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,::GetModuleHandle(TEXT(“DLL.dll“)),0); } 调用端代码: _declspec(dllimport) void SetHook(); SetHook();

VC中不用DLL在窗体中加入全局钩子

全局钩子是必须用DLL导出函数做的!但是线程钩子是可以做在程序里的!当全局钩子触发的时候,系统去DLL里寻找相关的触发函数!而不是在程序内部寻找的!所以假如你把钩子函数写在自己的程序内部,只能在你的程序是活动窗口的时候,消息才被触发的!但是你让程序失去输入焦点,钩子函数就会失效的!我很理解LZ的想法,我当初做全局钩子,也是不想要个DLL库的,觉得那很不美观的!但是Windows就是这样,她规定了的!没办法改的!假如你想捕捉很少的键盘消息,可以用注册热键的方法的!注册函数BOOL RegisterHotKey(HWND hWnd,intid,UINT fsModifiers,UINT vk);当你注册个热键的时候,热键一触发,就会给你设定的窗口发送消息的!参数:hWnd是接受热键触发消息的窗口id:是热键的标识符,为了使热键不冲突!fsModifoers是热键控键的组成部分!比如说你想把热键设置成ALT+S,那fsModifoers就是ALT部分,她总共有3个标识符MOD_ALTMOD_SHIFTMOD_WINvk是除了控制键其他的键!假如想截获多个控制键,比如ALT+SHIFT+S fsModifoers就可以写成MOD_ALT|MOD_SHIFT, vk写成s;

回调函数到底是怎么回事

给你讲过实用点的,在MFC中很多都是回调函数,都是通过事件触发的,但是我们在写程序的时候也经常用到自己写的回调函数,回调函数和一般函数体一样只不过在调用的时候是给触发条件传入一个函数指针由这个函数指针指向你自己的回调函数然后由你设置的这个条件去调用你自己写的回调函数也就是你可以自己写个函数,然后在里面用一个指向函数的指针指身一个回调函数当然在这个函数被调用的时候也就会去调用你定义的回调函数了举个例给你看我们在使用键盘钩子的时候就会用到一个回调函数 // 回调函数指针typedef BOOL (CALLBACK* LPFNKEYBOARDPROC)(WPARAM, KBDLLHOOKSTRUCT*);LPFNKEYBOARDPROC g_lpfnKeyboardProc; // 键盘钩子回调函数指针// 底层键盘钩子函数LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam){if (nCode 》= HC_ACTION){KBDLLHOOKSTRUCT* pStruct = (KBDLLHOOKSTRUCT*)lParam;if (g_lpfnKeyboardProc(wParam, pStruct))//注意这里的g_lpfnKeyboardProc是一个函数指针,指向一个函数,在我们判断这个函数指针的时候其实也就调用了我们定义的回调函数,当然这个函数的函数体没有写出来了return CallNextHookEx(g_hHook, nCode, wParam, lParam);elsereturn true;// 调用系统中的下一个钩子return CallNextHookEx(g_hHook, nCode, wParam, lParam);}void SetHook(LPFNKEYBOARDPROC lpfnKeyboardProc){g_lpfnKeyboardProc = lpfnKeyboardProc;//安装的时候传入一个函数指针g_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, g_hInstance, NULL); //这里用到的LowLevelKeyboardProc就是一个回调函数,它是在我们设置这个键盘钩子的时候被调用其函数体在上面,和我们普通函数是一样的}

键盘钩子怎么 使用

I:设置钩子设置钩子是通过SetWindowsHookEx ()的API函数.原形: HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hMod,DWORD dwThreadId)idhook:装入钩子的类型.lpfn: 钩子进程的入口地址hMod: 应用程序的事件句柄dwThreadId: 装入钩子的线程标示参数:idHook:这个参数可以是以下值:WH_CALLWNDPROC、WH_CALLWNDPROCRET、WH_CBT、WH_DEBUG、WH_FOREGROUNDIDLE、WH_GETMESSAGE、WH_JOURNALPLAYBACK、WH_JOURNALRECORD、WH_KEYBOARD、WH_KEYBOARD_LL、WH_MOUSE、WH_MOUSE_LL、WH_MSGFILTER、WH_SHELL、WH_SYSMSGFILTER。对于这些参数,我不想一一加以解释,因为MSDN中有关于他们的详细注解。我只挑选其中的几个加以中文说明。WH_KEYBOARD:一旦有键盘敲打消息(键盘的按下、键盘的弹起),在这个消息被放在应用程序的消息队列前,WINDOWS将会调用你的钩子函数。钩子函数可以改变和丢弃键盘敲打消息。WH_MOUSE:每个鼠标消息在被放在应用程序的消息队列前,WINDOWS将会调用你的钩子函数。钩子函数可以改变和丢弃鼠标消息。WH_GETMESSAGE:每次当你的应用程序调用一个GetMessage()或者一个PeekMessage()为了去从应用程序的消息队列中要求一个消息时,WINDOWS都会调用你的钩子函数。而钩子函数可以改变和丢弃这个消息。II:释放钩子钩子的释放使用的是UnhookWindowsHookEx()函数原形:BOOL UnhookWindowsHookEx( HHOOK hhk )UnhookWindowsHookEx()函数将释放的是钩子链中函数SetWindowsHookEx所装入的钩子进程。hhk: 将要释放的钩子进程的句柄。III:钩子进程钩子进程使用函数HookProc;其实HookProc仅仅只是应用程序定义的符号。比如你可以写成KeyBoardHook.但是参数是不变的。Win32 API提供了诸如:CallWndProc、GetMsgProc、DebugProc、CBTProc、MouseProc、KeyboardProc、MessageProc等函数,对于他们的详细讲解,可以看MSDN我在此只讲解一下KeyBoardHook的含义。原形:LRESULT CALLBACK KeyBoardHook (int nCode, WPARAM wParam, LPARAM lParam)说明:钩子进程是一些依附在一个钩子上的一些函数,因此钩子进程只被WINDOWS调用而不被应用程序调用,他们有时就需要作为一个回调函数(CALLBACK)。参数说明:nCode:钩子代码,钩子进程使用钩子代码去决定是否执行。而钩子代码的值是依靠钩子的种类来定的。每种钩子种类都有他们自己一系列特性的代码。比如对于WH_KEYBOARD,钩子代码的参数有:HC_ACTION,HC_NOREMOVE。HC_ACTION的意义:参数wParam 和lParam 包含了键盘敲打消息的信息,HC_NOREMOVE的意义:参数wParam 和lParam包含了键盘敲打消息的信息,并且,键盘敲打消息一直没有从消息队列中删除。(应用程序调用PeekMessage函数,并且设置PM_NOREMOVE标志)。也就是说当nCode等于HC_ACTION时,钩子进程必须处理消息。而为HC_NOREMOVE时,钩子进程必须传递消息给CallNextHookEx函数,而不能做进一步的处理,而且必须有CallNextHookEx函数的返回值。 wParam:键盘敲打所产生的键盘消息,键盘按键的虚拟代码。lParam:包含了消息细节。 注意:如果钩子进程中nCode小于零,钩子进程必须返回(return) CallNextHookEx(nCode,wParam,lParam);而钩子进程中的nCode大于零,但是钩子进程并不处理消息,作者推荐你调用CallNextHookEx并且返回该函数的返回值。否则,如果另一个应用程序也装入WH_KEYBOARD 钩子,那么该钩子将不接受钩子通知并且返回一个不正确的值。如果钩子进程处理了消息,它可能返回一个非零值去阻止系统传递该信息到其它剩下的钩子或者windows进程。所以最好在钩子进程的最后都返回CallNextHookEx的返回值。 IV:调用下一个钩子函数调用下一个钩子函数时使用CallNexHookEx函数。原形:LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam )CallNexHookEx()函数用于对当前钩子链中的下一个钩子进程传递钩子信息,一个钩子进程既可以在钩子信息处理前,也可以在钩子信息处理后调用该函数。为什么使用该函数已在iii钩子进程中的“注意”中,加以了详细的说明。hhk: 当前钩子的句柄nCode: 传送到钩子进程的钩子代码。wParam:传送到钩子进程的值。lParam:传送到钩子进程的值。参数:hhk: 当前钩子的句柄. 应用程序接受这个句柄,作为先前调用SetWindowsHookE函数的结果 nCode: 传送到钩子进程的钩子代码,下一个钩子进程使用这个代码以此决定如何处理钩子信息 wParam:传送给钩子进程的wParam 参数值 ,参数值的具体含义与当前钩子链的挂接的钩子类型有关lParam : 传送给钩子进程的wParam 参数值 ,参数值的具体含义与当前钩子链的挂接的钩子类型有关 返回值:返回值是链中下一个钩子进程返回的值,当前钩子进程必须返回这个值,返回值的具体含义与挂接的钩子类型有关,详细信息请参看具体的钩子进程描述。V 建立一个动态连接库(DLL)当我们熟悉了以上的各个函数后,现在我们开始编写一个动态连接库(DLL)。在这儿我采用的是WIN32 DLL,而不是MFC DLL。而且以下所有的程序也都是采用C语言去编写。这主要是因为使用WIN32 API能够更详细、更全面的控制程序的如何执行,而使用MFC,一些低级的控制是不可能实现的(当然,仅对该程序来说,也是可以使用MFC的)。1:建立一个动态连接库的.cpp文件。比如我们现在建立一个名为hookdll.cpp的文件。在hookdll.cpp的文件中加上如下内容:#include 《windows.h》#include “string.h“#include “stdio.h“ HINSTANCE hInst;#pragma data_seg(“hookdata“)HHOOK oldkeyhook=0;#pragma data_seg()#pragma comment(linker,“/SECTION:hookdata,RWS“)#define DllExport extern “C“__declspec(dllexport)DllExport LRESULT CALLBACK KeyBoardProc(int nCode,WPARAM wParam, LPARAM lParam );DllExport void InstallHook(int nCode);DllExport void EndHook(void);BOOL WINAPI DllMain(HINSTANCE hInstance,ULONG What,LPVOID NotUsed){switch(What){case DLL_PROCESS_ATTACH:hInst = hInstance;break;case DLL_PROCESS_DETACH:break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break; }return 1;}void InstallHook(int nCode){oldkeyhook = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyBoardProc,hInst,0);}DllExport LRESULT CALLBACK KeyBoardProc(int nCode,WPARAM wParam, LPARAM lParam ){WPARAM j;FILE *fp;if(lParam&0x80000000){j = wParam;fp=fopen(“c:\hook\key.txt“,“a“); fprintf(fp,“%4d“,j);fclose(fp);}return CallNextHookEx(oldkeyhook,nCode,wParam,lParam);}void EndHook(void){UnhookWindowsHookEx(oldkeyhook);}这个动态连接库的源代码hookdll.cpp包含了键盘处理函数,设置钩子,退出钩子函数。并将键盘敲下的键以值的格式存入到c:hookkey.txt文件中。以下是对该文件的详细的解释。使用包含在DLL的函数,必须将其导入。导入操作时通过dllimport来完成的,dllexport和dllimport都是vc(visual C++)和bc(Borland C++)所支持的扩展的关键字。但是dllexport和dllimport关键字不能被自身所使用,因此它的前面必须有另一个扩展关键字__declspec。通用格式如下:__declspec(specifier)其中specifier是存储类标示符。对于DLL,specifier将是dllexport和dllimport。而且为了简化说明导入和导出函数的语句,用一个宏名来代替__declspec.在此程序中,使用的是DllExport。如果用户的DLL被编译成一个C++程序,而且希望C程序也能使用它,就需要增加“C”的连接说明。#define DllExport extern “C“__declspec(dllexport),这样就避免了标准C++命名损坏。(当然,如果读者正在编译的是C程序,就不要加入extern “C”,因为不需要它,而且编译器也不接受它)。有了宏定义,现在就可以用一个简单的语句就可以导出函数了,比如:DllExport LRESULT CALLBACK KeyBoardProc(int nCode,WPARAM wParam, LPARAM lParam );DllExport void InstallHook(int nCode);DllExport void EndHook(void);第一个#pragma 语句创造数据段,这里命名为hookdata。其实也可以命名为您喜欢的任意的一个名称。#pragma 语句之后的所有初始化的变量都进入hookdata段中。第二个#pragma语句是数据段的结束标志。对变量进行专门的初始化是很重要的,否则编译程序将把它们放在普通的未初始化的段中而不是放在hookdata中。但是链接程序必须直到有一个hookdata段。我们可以在Project Setting(vc6.0) 对话框中选择Link选项,选中HOOKDLL时在Project Options域(在Release 和Debug配置中均可),包含下面的连接语句:/SECTION:hookdata,RWS字母RWS是表明该段具有读、写、和共享属性。当然,您也可以直接用DLL源代码指定链接程序就像HOOKDLL.c那样:#pragma comment(linker,“/SECTION:hookdata,RWS“)。由于有些DLL需要特殊的启动和终止代码。为此,所有的DLL都有一个名为DllMain()的函数,当初始化或终止DLL时调用该函数。一般在动态连结库的资源文件中定义此函数。不过如果没有定义它,则编译器会自动提供缺省的形式。原型为:BOOL WINAPI DllMain(HINSTANCE hInstance,ULONG What,LPVOID NotUsed)参数:hInstance:DLL实例句柄What:指定所发生的操作NotUsed:保留参数其中What的值可以为以下值:DLL_PROCESS_ATTACH:进程开始使用DLLDLL_PROCESS_DETACH:进程正在释放DLLDLL_THREAD_ATTACH:进程已创建一个新的线程DLL_THREAD_DETACH:进程已舍弃了一个线程总的来说,无论何时调用DllMain()函数,都必须根据What的内容来采取适当的动作。这种适当的动作可以什么都不做,但不是返回非零值。 DllMain()接下来的便是设置钩子,键盘处理,和释放钩子。 2:建立头文件正如应用程序所使用的其它任何库函数一样,程序也必须包含dll内的函数的原型。所有得Windows程序都必须包含windows.h的原因。所以我们现在建立一个头文件hookdll.h如下:#define DllImport extern“C“__declspec(dllimport)DllImport void InstallHook(int nCode);DllImport LRESULT CALLBACK KeyBoardProc (int nCode,WPARAM wParam, LPARAM lParam );DllImport void EndHook(void);使用dllimport主要是为了使代码更高效,因此推荐使用它。但是在导入数据时是需要dllimport的。当完成了上面的程序后,建一个项目工程,不妨为hookdll,然后将hookdll.c插入导项目工程中,编译,则可以生成了hookdll.dll和hookdll.lib。3:建立程序主文件我们在上面作的所有得工作都是为现在的主程序打得基础。其实当我们完成了Dll文件后,剩下的就是调用设置钩子函数:InstallHook 。如果你对windows编程十分的熟悉,那么你可以在你任何需要的时候来调用InstallHook。但是在你必须记住在你退出程序的时候你需要调EndHook以便释放你所装入的钩子函数。现在我在建立了一个hookspy.cpp,并将生成好的hookdll.dll和hookdll.lib拷贝到从一个目录下,并建立一个hookspy的项目工程。将hookspy.cpp,hookdll.dll,hookdll.lib,hookdll.h插入到项目工程中去。然后在建立windows窗口时就将钩子设置,在退出程序时退出钩子函数。比如:case WM_CREATE:InstallHook(TRUE);break;case WM_DESTROY: //terminate the programEndHook();PostQuitMessage(0);break;

C++全局键盘勾子的问题

在return CallNextHookEx(g_Keyboard,code,wParam,lParam);之前加上fclose(pFile)原因如下:当你对话框没有隐藏的时候,你对话框所在的进程(你就是你程序的进程)打开了文件,但没有关闭文件,所以当然进程就占有了这个文件,当你隐藏之后,其它进程成为活动进程,响应键盘消息,进入钩子函数,但执行fopen()却会失败,因为文件已经被你之前的进程所占有。当然也就无法写入数据了。


声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,谢谢。

上一篇: 不变心的句子,关于不变心的句子(写给很想念却难相见的你)

下一篇: 遗憾的过客是什么意思(把遗憾写到极致的句子)



推荐阅读