简易的识别大小写的键盘钩子

初学钩子方面的知识,回想到一些游戏盗号的程序也是这个原理,觉得有必要好好了解一下。

代码段是我找了一个基本的局部键盘钩子之后修改了一下,由于我发现得到的键盘码都是大写的,那么怎么判断用户输入的究竟是大写还是小写呢?

 

我们通过判断shift键和大写锁定键这两个键的状态来确定输入的是大写还是小写,用到的函数是GetKeyState和GetAsyncKeyState,判断CapsLock只能用前者,判断Shift只能用后者,GetAsyncKeyState在按下某键的同时调用,判断正在按下某键。GetKeyState则在按过某键之后再调用,它返回最近的键盘消息从线程的队列中移出时的键盘状态,判断刚按过了某键(请自行思考脉冲信号)。这两个键对应的虚拟键值是VK_SHIFT和VK_CAPITAL

 

使用GetKeyState获得返回值后,我们发现,当capslock按下时,返回-127,对应二进制是1111111100000001,没按下时返回0

shift键则是按下时为1,对应二进制 1000 0000 0000 0001,没按下时返回0

 

按照MSDN上面的说明

 

  • If the high-order bit is 1, the key is down; otherwise, it is up.
  • If the low-order bit is 1, the key is toggled. A key, such as the caps lock key, is toggled if it is turned on. The key is off and untoggled if the low-order bit is 0. A toggle key's indicator light (if any) on the keyboard will be on when the key is toggled, and off when the key is untoggled.

 

高位为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通信才是王道哇咔咔)

你可能感兴趣的:(c,socket,action,callback,hook,keyboard)