面对现实,超越自己
逆水行舟,不进则退
posts - 269,comments - 32,trackbacks - 0

MSDN中解释:
Determines whether a key is up or down at the time the function is called, and whether the key was pressed after a previous call to GetAsyncKeyState.

Syntax

SHORT WINAPI GetAsyncKeyState(   _In_  int vKey );

Parameters

vKey [in]

Type: int

The virtual-key code. For more information, see Virtual Key Codes.

You can use left- and right-distinguishing constants to specify certain keys. See the Remarks section for further information.

Return value

Type: SHORT

If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState. However, you should not rely on this last behavior; for more information, see the Remarks.

The return value is zero for the following cases:

  • The current desktop is not the active desktop
  • The foreground thread belongs to another process and the desktop does not allow the hook or the journal record. 


    以下转自:http://bingtears.iteye.com/blog/663149

    0x8000 & GetKeyState(VK_SHIFT); 这句是判断是否有按下shift键 

    为什么GetAsyncKeyState()& 

    首先说明,有好多程序或书上是0x8000f,这个f不是十六进制的f而是代表浮点数。其实& 8000才是本质。小鱼我整理后自己写了点东西,总结一下 


    首先介绍一下几个概念: 
    按位与运算符"&":是双目运算符,其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。例如:0x11 & 0x12(即0001 0001 & 0001 0010)的结果是0x10(0001 0000);(关于vs取反参考附) 
    虚键:指的是非字母可以明确表示的键.(例如ESC BS TAB NumLock 等,虚键列表见附); 
    物理键状态:在操作系统的控制面板中设置鼠标左右键的映射(实际的鼠标左键可以映射成右键点击事件),或者通过程序也可以这样设置,这样就产生了(实际的)物理键状态; 
    逻辑键状态:使用 GetKeyState,GetKeyboardState,等函数得到的逻辑键状态,模拟按下按键; 
    GetAsyncKeyState函数功能:读取的是物理键状态,也是就是不管你怎么鼠标键盘映射,它只读取实际的按键状态。MSDN上给出了例子很恰当For example, the call GetAsyncKeyState(VK_LBUTTON) always returns the state of the left physical mouse button, regardless of whether it is mapped to the left or right logical mouse button.也就是说如果你重新设置了映射,GetAsyncKeyState还是只读取物理状态; 
    GetAsyncKeyState的返回值:表示两个内容,一个是最高位bit的值,代表这个键是否被按下,按下为1,抬起为0;一个是最低位bit的值,在windowsCE下要忽略(参考自MSDNIf the most significant bit is set, the key is down. The least significant bit is not valid in Windows CE, and should be ignored.) 
    Asynchronous:英文意思是异步的 

    实际当中GetAsyncKeyState的返回值是什么呢?小鱼我写了个程序来获取返回值: 
    #include <Windows.h> 
    #include <stdio.h> 

    void main() 

    while(1) 

    short a = ::GetAsyncKeyState(VK_LSHIFT) 
    printf( "0x%x",a); 
    sleep(10); 


    当然,用MessageBox可以这样写: 
    if(short a = ::GetAsyncKeyState(VK_LSHIFT)) 

    char buffer[30]; 
    sprintf(buffer, "0x%x",a); 
    MessageBox(0, buffer, "a的值", MB_OK); 


    GetAsyncKeyState按键不按或抬起后不按的返回值0x0        即0000 0000 0000 0000 0000 0000 0000 0000 
    GetAsyncKeyState按键被按下后的返回值    返回0xffff8001 即1111 1111 1111 1111 1000 0000 0000 0001   (这里并不是返回4字节,而是%x打印出32位,前十六位补f) 
    0x8000 即0000 0000 0000 0000 1000 0000 0000 0000 
    GetAsyncKeyState(VK_LSHIFT) & 0x8000    返回0x1          即0000 0000 0000 0000 1000 0000 0000 0000 

    那么为什么GetAsyncKeyState要 ‘与’上 0x8000这个常数呢? 
    答案是:获取按键状态,屏蔽掉其他的可能状态,按照MSDN上说低位should ignore。 
    网上有人这样写,意思很明确: 
    #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) 
    #define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) 

    程序应该是: 
    if(GetAsyncKeyState(VK_LSHIFT)&&0x8000) 
    对于虚键而言下面这样写逻辑是不对的,虽然结果一样: 
    if(GetAsyncKeyState(VK_LSHIFT)) 

    所以让键盘的"上下左右"出发事件可以这样写: 
    if( ::GetAsyncKeyState(VK_LEFT) & 0x8000 ) 
    code... 
    if( ::GetAsyncKeyState(VK_RIGHT)& 0x8000 ) 
    code... 
    if( ::GetAsyncKeyState(VK_UP) & 0x8000 ) 
    code... 
    if( ::GetAsyncKeyState(VK_DOWN) & 0x8000 ) 
    code... 

    关于GetAsyncKeyState与GetKeyState区别: 
    GetAsyncKeyState上面已经讲差不多了,关于GetAsyncKeyState与GetKeyState二者最大区别:GetAsyncKeyState在按键不按的情况下为0,而GetKeyState在按键不按的情况下开始为0,当一次‘按下抬起’后变为1,依次循环。 

    SHORT GetKeyState(int nVirtKey   // virtual-key code); 
    作用:返回键的状态,按下、释放或锁定(down、up or toggled) 
    参数:虚拟键代码(VK_)。如果是字母a-z、A-Z 或数字0-9, 则为其对应的ASCII码(比如字母O的ASCII码为十六进制的0x4F) 
    返回值:返回码的高位显示当前是否有键被按下,低位(0位)则显示NumLock、CapsLock、ScrollLock的状态(ON或OFF,为ON时键盘指示灯亮)。即高位为1,返回值小于0,说明有键按下;最低位为1表示处于锁定(ON)状态(参考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. ) 
    注:此函数不应该在键盘消息处理程序以外使用,因为它返回的信息只有在键盘消息从消息队列中被检索到之后才有效。若确实需要,请使用GetAsyncKeyState 

    ---------------------------------------- 
    网上还找到了一些资料: 

    关于和其他的几个函数的区别: 
    SHORT GetKeyState(int nVirtKey); 
    SHORT GetAsyncKeyState(int vKey); 
    BOOL GetKeyboardState(PBYTE lpKeyState); 

    三个取key status的函数的最大区别是: 
    第一个:是从windows消息队列中取得键盘消息,返回key status. 
    第二个:是直接侦测键盘的硬件中断,返回key status. 
    第三个:是当从windows消息队列中移除键盘消息时,才返回key status. 

    keybd_event函数,是模拟键盘击键,一次完整的击键模拟事件,是"按下"和"弹起"两个消息,所以 keybd_event(VK_F12,0,0,0);keybd_event(VK_F12,0,KEYEVENTF_KEYUP,0); 完成了一次完整的点击 F12 的事件。 

    GetAsyncKeyState()函数,是直接侦测键盘的硬件中断。(有些人说,是一种“实时性”的侦测,这种说法,感觉不对,比如你调用 Sleep(),就算是中断一年的时间,只要在这期间程序还在运行,它都可以把那个键的状态侦测出来)。自上一次调用GetAsyncKeyState()函数以来(在某些循环中,N次调用GetAsyncKeyState(),它每次检查的,都是自上次调用之后,键的状态),若键已被按过,则返回1,否则,返回0;有些资料显示:倘若输入焦点从属于与调用函数的输入线程不同的另一个线程,则返回零(例如,在另一个程序拥有输入焦点时,应该返回零)。实验证明,这种说法并不完全,函数实际是在大部份范围内工作的,只有少数是另外)。 
posted on 2012-11-23 15:55 王海光 阅读(1640) 评论(0)  编辑 收藏 引用 所属分类: MFC

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理