如何使用windows api c ++处理“alt”击键

时间:2017-03-13 04:21:51

标签: c++ winapi

我正在尝试处理“alt”按键但没有任何反应。 我在Windows和winuser库中使用C ++

#include <windows.h>
#include <winuser.h>
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 
{
    KBDLLHOOKSTRUCT *hook=(KBDLLHOOKSTRUCT *)lParam;
    std::string input;
    if (wParam == WM_KEYUP) {
         input = Key::get(hook->vkCode, 1);
    } 
    else if (wParam == WM_KEYDOWN) {
    input = Key::get(hook->vkCode, 0);
    }
    Key::print(input);
    return 0;
}

我可以处理所有键盘,除了Key :: get()函数中的“alt”键。 有谁知道如何处理它?

std::string get(int code, int up) {
    std::string input;
    switch(code) {
        case 0x12: input = "[ALT]"; break;
    }
    return input;

[编辑]它实际上是一个WM_SYSKEYDOWN消息,应该用来处理alt键,我认为我发布的最后一个代码就足以看出问题所在。我没有发布程序,问题出在哪里。感谢大家的回答。

1 个答案:

答案 0 :(得分:1)

0x12看起来像Windows API会返回,但你是如何获得的?但检查它是不够的。避免使用&#34; magic&#34;数字,该代码名为VK_MENU。

  

WM_KEYDOWN消息

     

当非系统密钥出现时,使用键盘焦点发布到窗口   按下。非系统密钥是在ALT密钥为时按下的密钥   没有按下。

     

wParam 非系统密钥的虚拟密钥代码。请参阅虚拟密钥   代码。

     

lParam 重复计数,扫描码,扩展键标志,上下文   代码,先前的键状态标志和转换状态标志,如图所示   以下

     
      
  • 0-15当前消息的重复计数。该值是用户导致击键自动重复的次数   按住钥匙。如果按键保持足够长,则多次   消息被发送。但是,重复计数不是累积计数。
  •   
  • 16-23扫描码。价值取决于OEM。
  •   
  • 24表示密钥是否为扩展密钥,例如增强型101上显示的右侧ALT和CTRL键,或者   102键键盘。如果它是扩展密钥,则值为1;除此以外,   它是0.
  •   
  • 25-28保留;不使用。
  •   
  • 29上下文代码。对于WM_KEYDOWN消息,该值始终为0。
  •   
  • 30上一个关键状态。如果在发送消息之前密钥已关闭,则值为1;如果密钥已启动,则该值为零。
  •   
  • 31过渡状态。对于WM_KEYDOWN消息,该值始终为0.
  •   
     

WM_SYSKEYDOWN消息

     

当用户按下时,用键盘焦点发布到窗口   F10键(激活菜单栏)或按住ALT键和   然后按另一个键。当没有窗口时也会发生这种情况   键盘焦点;在这种情况下,WM_SYSKEYDOWN消息被发送到   活动窗口。接收消息的窗口可以   通过检查上下文代码来区分这两个上下文   lParam参数。

     

wParam 正在按下的键的虚拟键代码。请参阅虚拟密钥   代码。

     

lParam 重复计数,扫描码,扩展键标志,上下文   代码,先前的键状态标志和转换状态标志。

如果您使用Get \ PeekMeessage,这样的内容可以解释可能性:

// Receives a WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN or WM_SYSKEYUP message and 
// returns a virtual key of the key that triggered the message.
// 
// If the key has a common virtual key code, that code is returned. 
// For Alt's and Ctrl's, the values from the KeyCodes enumeration are used.
int translateKeyMessage (MSG& Msg);

// Virtual key codes for keys that aren't defined in the windows headers.
enum KeyCodes
{
    VK_LEFTCTRL = 162,
    VK_RIGHTCTRL = 163,
    VK_LEFTALT = 164,
    VK_RIGHTALT = 165
};


int translateKeyMessage (MSG& Msg)
{
    // Determine the virtual key code.
    int VirtualKeyCode = Msg.wParam;

    // Determine whether the key is an extended key, e.g. a right 
    // hand Alt or Ctrl.
    bool Extended = (Msg.lParam & (1 << 24)) != 0;

    // If this is a system message, is the Alt bit of the message on?
    bool AltBit = false;    
    if (Msg.message == WM_SYSKEYDOWN || Msg.message == WM_SYSKEYUP)
        AltBit = (Msg.lParam & (1 << 29)) != 0;

    if ((Msg.message == WM_SYSKEYUP || Msg.message == WM_KEYUP) && !Extended && !AltBit && VirtualKeyCode == VK_MENU)
    {
        // Left Alt
        return KeyCodes::VK_LEFTALT;
    }

    // Left Ctrl
    if (!Extended && !AltBit && VirtualKeyCode == VK_CONTROL)
    {
        // Peek for the next message.
        MSG nextMsg;
        BOOL nextMessageFound = PeekMessage(&nextMsg, NULL, 0, 0, PM_NOREMOVE);

        // If the next message is for the right Alt:
        if (nextMessageFound && nextMsg.message == Msg.message && nextMsg.wParam == VK_MENU)
        {
            //
            bool nextExtended = (nextMsg.lParam & (1 << 24)) != 0;

            //
            bool nextAltBit = false;    
            if (nextMsg.message == WM_SYSKEYDOWN || nextMsg.message == WM_SYSKEYUP)
                nextAltBit = (nextMsg.lParam & (1 << 29)) != 0;

            // If it is really for the right Alt
            if (nextExtended && !nextAltBit)
            {
                // Remove the next message
                PeekMessage(&nextMsg, NULL, 0, 0, PM_REMOVE);

                // Right Alt
                return KeyCodes::VK_RIGHTALT;
            }
        }

        // Left Ctrl
        return KeyCodes::VK_LEFTCTRL;
    }

    if (Msg.message == WM_SYSKEYUP && !Extended && AltBit && VirtualKeyCode == VK_CONTROL)
    {
        // Peek for the next message.
        MSG nextMsg;
        BOOL nextMessageFound = PeekMessage(&nextMsg, NULL, 0, 0, PM_NOREMOVE);

        // If the next message is for the right Alt:
        if (nextMessageFound && nextMsg.message == WM_KEYUP && nextMsg.wParam == VK_MENU)
        {
            //
            bool nextExtended = (nextMsg.lParam & (1 << 24)) != 0;

            //
            bool nextAltBit = false;    
            if (nextMsg.message == WM_SYSKEYDOWN || nextMsg.message == WM_SYSKEYUP)
                nextAltBit = (nextMsg.lParam & (1 << 29)) != 0;

            // If it is really for the right Alt
            if (nextExtended && !nextAltBit)
            {
                // Remove the next message
                PeekMessage(&nextMsg, NULL, 0, 0, PM_REMOVE);

                // Right Alt
                return KeyCodes::VK_RIGHTALT;
            }
        }
    }

    // Right Ctrl
    if (Extended && !AltBit && VirtualKeyCode == VK_CONTROL)
        return KeyCodes::VK_RIGHTCTRL;

    // Left Alt
    if (!Extended && AltBit && VirtualKeyCode == VK_MENU)
        return KeyCodes::VK_LEFTALT;

    // Default
    return VirtualKeyCode;
}