C语言 如何在WM_KEYDOWN事件中区分LQs和RQs?

tvmytwxo  于 2023-10-16  发布在  其他
关注(0)|答案(4)|浏览(131)

根据MSDNwParam应该保存密钥代码。问题是,当按Shift键时,键码是16(VK_SHIFT),但我需要区分VK_LSHIFTVK_RSHIFT
对于VK_CONTROL,似乎有一个解决方案:

if (wParam == VK_CONTROL) {
    if (lParam & EXTENDED_KEYMASK)
        wParam = VK_RCONTROL;
    else
        wParam = VK_LCONTROL;
}

但是,对于VK_SHIFT来说,这并不起作用:

if (wParam == VK_SHIFT) {
    if (lParam & EXTENDED_KEYMASK)
        wParam = VK_RSHIFT;
    else
        wParam = VK_LSHIFT;
}

在后一个示例中,它将始终假设Lvid。

t98cgbkg

t98cgbkg1#

要区分Shift、Ctrl或Alt键的左右版本,必须使用MapVirtualKey()函数或与虚拟键消息一起传递的lParam中的“扩展键”位。下面的函数将为您执行转换-只需传入虚拟键码和来自消息的lParam,您将获得相应的左/右特定虚拟键码:

WPARAM MapLeftRightKeys( WPARAM vk, LPARAM lParam)
{
    WPARAM new_vk = vk;
    UINT scancode = (lParam & 0x00ff0000) >> 16;
    int extended  = (lParam & 0x01000000) != 0;

    switch (vk) {
    case VK_SHIFT:
        new_vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
        break;
    case VK_CONTROL:
        new_vk = extended ? VK_RCONTROL : VK_LCONTROL;
        break;
    case VK_MENU:
        new_vk = extended ? VK_RMENU : VK_LMENU;
        break;
    default:
        // not a key we map from generic to left/right specialized
        //  just return it.
        new_vk = vk;
        break;    
    }

    return new_vk;
}

如果传入的虚拟键码不是Map到左/右版本的键码,则原始键码将不作更改地传回。因此,只要需要区分左右变量,就可以通过函数运行WM_KEYDOWN/WM_KEYUP/WM_SYSKEYDOWN/WM_SYSKEYUP消息参数。
通过使用MapVirtualKey(),您不需要知道左移和右移扫描码是0x 2a和0x 36的知识-API会处理这些细节。如果它们确实发生了变化(并不是说真的会发生),Windows将负责处理它,而不是你。
因此,在WM_KEYDOWN/WM_KEYUP/WM_SYSKEYDOWN/WM_SYSKEYUP处理程序中,您只需添加一行代码,如下所示:

wparam = MapLeftRightKeys(wparam, lparam);

代码的其余部分可以作用于左/右特定的VK代码,就好像系统消息一开始就给了你一样。

7qhs6swi

7qhs6swi2#

你的问题背后有着古老的历史。最初的IBM PC键盘没有正确的Alt和Ctrl键。它们是后来在扩展键盘布局上添加的,键盘控制器将它们与0xe0前缀一起发送到扫描码,以将它们区分为扩展键。但最初的键盘布局总是有两个shift键,所以它们有自己的非扩展扫描码。所以你的代码不起作用。
大卫的回答是解决你问题的好方法。但你实际上可以从信息中得到它,那些扫描码是由Windows logo requirements铸成的。在lParam中可用,左shift键的扫描码为42,右shift键的扫描码为54。不幸的是,在Windows头文件中没有#define,这使得它变得丑陋。

0tdrvxhp

0tdrvxhp3#

通过VK_LSHIFTVK_RSHIFT调用GetKeyState

zpf6vheq

zpf6vheq4#

根据MSDN的说法:

  • VK_LSHIFT
  • VK_RSHIFT
  • VK_LCONTROL
  • VK_RCONTROL
  • VK_LMENU
  • VK_RMENU

应用程序只能通过GetKeyboardState、SetKeyboardState、GetAsyncKeyState、GetKeyState和MapVirtualKey函数使用这些区分左侧和右侧的常量。

相关问题