千万注意!使用GetAsyncKeyState检测窗口按键时要检查是否为前端窗口!

我先放一些图:

千万注意!使用GetAsyncKeyState检测窗口按键时要检查是否为前端窗口!_第1张图片
千万注意!使用GetAsyncKeyState检测窗口按键时要检查是否为前端窗口!_第2张图片
千万注意!使用GetAsyncKeyState检测窗口按键时要检查是否为前端窗口!_第3张图片
记住,这些同志都是没有注意到这个问题的


有时候比如说写游戏的时候都要检测玩家的按键,我们经常要么用getch(),要么就用GetAsyncKeyState(),我这里要强调一下后者的一个问题。
这个函数很常见,比如可以写成宏:

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) 
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

(那个& 0x8000还是要写的,低位忽略可是微软官网上说的)
很多人实际会这么写,上面也已经有很多例子了:

if( GetAsyncKeyState('A') & 0x8000 )
{
    p.x --;
    //还有一些坐标判断以及限制省略
}
else if( GetAsyncKeyState('D') & 0x8000 )
{
    p.x ++;
}
if( GetAsyncKeyState('W') & 0x8000 )
{
    p.y --;
}
else if( GetAsyncKeyState('S') & 0x8000 )
{
    p.y ++; 
}

(或者是检测VK_上下左右)

这样就出现了这个问题了,那就是
GetAsyncKeyState()是一个Windows全局用的函数,没有针对窗口。
千万注意!使用GetAsyncKeyState检测窗口按键时要检查是否为前端窗口!_第4张图片
你在别的地方输入一行文字,其中包括a,w,s,d,(中文也行)你发现你的游戏人物竟然动起来了!!!
万一你在哪里输个密码,岂不是字母都可以通过玩家的位移来推断了??!
所以如果你不进行窗口前端的判断就会造成 用 户 隐 私 泄 露 。
是不是很可怕?(别想着用这个函数窃听键盘,因为时间的问题是检测不出来的)

正确的解决方式见下,抓紧时间记住!

#define KEY_DOWN(VK) ((GetAsyncKeyState(VK)& 0x8000 ? 1:0))
#define KEY_DOWN_FOREGROUND(hWnd,vk) (KEY_DOWN(vk) && GetForegroundWindow() == hWnd) //前景窗口判断

其中hWnd为你的游戏或者什么程序的窗口句柄。
如果嫌麻烦:

#define K(sk) KEY_DOWN_FOREGROUND(hWnd,sk)

然后再去写实际的代码。这样才安全好吧。

另外,如果使用getch()或_getch(),是不会有任何泄露隐私的问题的,因为它们是针对程序窗口按键缓冲区的,和别的窗口没关系。

★ 还有一点,

检测鼠标位置的时候(当你直接使用GetCursorPos+ScreenToClient的时候) 也是同此,一定要检查是否为前端窗口,否则在别的窗口上晃鼠标 你那个窗口自己会变化甚至发出按钮音效 也很骇人!!
(当我发现泰拉瑞亚也有这个BUG的时候我惊呆了)

* 动动手指转发出去,以拯救更多的人!!!

你可能感兴趣的:(c++,windows,键盘,隐私安全)