想用c语言写一个全局键盘钩子的程序,成功后送100分!

Python014

想用c语言写一个全局键盘钩子的程序,成功后送100分!,第1张

全局键盘钩子是需要放到dll中去实现的

我估计你还不会写什么是dll

但有好消息告诉你

日志钩子可以做到在一个程序中实现全局键盘捕获:

VC代码:

#include<windows.h>

HHOOK LogHook=NULL

LRESULT CALLBACK LogProc(int code,WPARAM wParam,LPARAM lParam)

{

EVENTMSG *pEventMsg=(EVENTMSG*)lParam

if(code==HC_ACTION)

{

switch(pEventMsg->message)

{

case (WM_KEYDOWN):

BYTE bKeyState[256]

unsigned short uAscii[4]

UINT uScanCode

int iRet

GetKeyboardState(bKeyState)

bKeyState[VK_SHIFT]=GetKeyState(VK_SHIFT)

uScanCode=(pEventMsg->paramH>>16)

iRet=ToAscii(pEventMsg->paramL,uScanCode,bKeyState,uAscii,0)

switch(iRet)

{

case 0:

break

case 1:

if((char)uAscii[0]=='t' || (char)uAscii[0]=='T')//t键按下

{

MessageBox(NULL,"按下了T","按键提示",MB_OK)

/**************自己实现播放音乐的功能*****************/

}

else if((char)uAscii[0]=='y' || (char)uAscii[0]=='Y')//Y键按下

{

MessageBox(NULL,"按下了Y","按键提示",MB_OK)

/***************自己在这里实现停止播放音乐的功能****************/

}

break

default:

break

}

default:

break

}

}

return CallNextHookEx(LogHook,code,wParam,lParam)

}

int WINAPI WinMain( HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow

)

{

LogHook=SetWindowsHookEx(WH_JOURNALRECORD,LogProc,hInstance,NULL)

while(1)Sleep(100)

return 0

}

日志钩子工作不稳定的。

例子:

HWND hWnd = NULL//定义成全局变量

HHOOK hKeyboard

HHOOK hMouse

LRESULT CALLBACK MouseProc( int nCode, WPARAM wParam, LPARAM lparam )// 鼠标钩子函数

{

return 1 // 返回非零值表示已经对当前消息进行了处理,这样系统就不会再将这个消息传递给目标窗口过程

}

LRESULT CALLBACK KeyboardProc( int nCode, WPARAM wParam, LPARAM lparam )

if( VK_F4 == wParam &&(1 == (lparam>>29&1)) )// 系统后门:Alt+F4键退出程序

{

::SendMessageA( hWnd, WM_CLOSE, 0, 0 )

定义钩子函数

钩子函数是一种特殊的回调函数。钩子监视的特定事件发生后,系统会调用钩子函数进行处理。不同事件的钩子函数的形式是各不相同的。下面以鼠标钩子函数举例说明钩子函数的原型:

LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam)

参数wParam和 lParam包含所钩消息的信息,比如鼠标位置、状态,键盘按键等。nCode包含有关消息本身的信息,比如是否从消息队列中移出。 我们先在钩子函数中实现自定义的功能,然后调用函数 CallNextHookEx.把钩子信息传递给钩子链的下一个钩子函数。CallNextHookEx.的原型如下:

LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam ) 参数 hhk是钩子句柄。nCode、wParam和lParam 是钩子函数。

当然也可以通过直接返回TRUE来丢弃该消息,就阻止了该消息的传递。

知道动态链接库的底层实现么?

一个动态链接库在物理内存中只被装入一次

意味着你的dll在内存中只有一个副本

一个进程加载你的dll这个过程仅仅是操作系统把那块dll物理内存所对的那块内存加载到这个进程的逻辑地址(地址空间)罢了

怎么可能内存浪费?

所有进程都加载了你的dll,那个dll在实际内存中也只有一个副本

这就是动态链接库的好处

PS::dll被动加载(不是用LoadLibrary加载)是以进程为单位的。。。。下次不要说一个线程加载了dll了。。。。即使一个线程加载了那个dll,那个dll也是被那个进程共享的

对你的问题的补充

我只补充一点:对于任何一个dll,都是可以被共享的

如果两个进程a和b都需要加载动态链接库1.dll

那操作系统负责把1.dll装入物理内存

然后把这块内存区域的数据(在逻辑上)加载到进程a和进程b的虚拟地址空间中(按照a和b的输入表以及重定位信息装入到一个地址中)

所谓逻辑上加载就是并没有在实际内存中额外创建一个1.dll的副本

当a.进程退出时,1.dll继续停留在内存中,当b进程退出时,操作系统会知道模块1.dll在内存中已经不被需要了就会回收这块内存。

这就是动态链接库的好处,除代码重用之外还能减少内存占用!(无论是在开发上,还是在实际使用上,动态链接库都有着不可取代的高效)

另外我想我上面的回答已经够详细了

还不懂,那我也没办法

二楼的解释纯属扯谈

全局钩子就是需要操作系统把这个dll映射到每一个进程中去的。

但这样就是常驻内存吗?请问二楼你写过全局钩子吗?请问二楼你写代码的时候申请了一块内存有释放掉这块内存的习惯吗?

我请问你听说过Windows API :

UnhookWindowsHookEx

(

HHOOK hhk

)

吗?没听说过请别瞎扯 ,ok?

全局钩子就是要钩全局的事件,为何要指定释放?需要指定释放那创建钩子的时候为什么不用进程钩子?不吐槽了,无奈~~

不懂windows运行机制最好不要上来误导不懂的人,谢谢

楼主如果只是做开发的,那你只需要知道全局键盘钩子不需要任何额外内存就可以运行得很好,操作系统能做到把一块物理内存上的 dll数据加载到每一个进程地址空间中去~

楼主如果想要把这个过程了解清楚

请参阅windows编程以及windows操作系统的相关书籍

如果能看懂《windows环境下32位汇编语言程序设计》这本书,那你几乎问不出任何windows编程的问题了~