4

I try to use the Windows API in c++ and SetWindowsHookEx WH_KEYBOARD_LL does not seem to get events from the right Shift key (the Shift key at the right side of a qwerty keyboard, below the Enter key). It does work with the left Shift key. How do I troubleshoot this problem???

#include "stdafx.h"
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <string>
#include <windows.h>
#include <string> 
#include <shlobj.h>
#include <Shlwapi.h>
#include <stdio.h>
#include <aclapi.h>
#include <tchar.h>
#include <iostream>
#include <fstream>
#include <future>
#include <stdlib.h>
#include <random>
#include <ctime>
#include <time.h>       
#include <Lmcons.h>



HHOOK   kbdhook;    /* Keyboard hook handle */
bool    running;    /* Used in main loop */


__declspec(dllexport) LRESULT CALLBACK handlekeys(int code, WPARAM wp, LPARAM lp)
{
        static bool capslock = false;
        static bool shift = false;
        char tmp[0xFF] = {0};
        std::string str;
        DWORD msg = 1;
        KBDLLHOOKSTRUCT st_hook = *((KBDLLHOOKSTRUCT*)lp);



        msg += (st_hook.scanCode << 16);
        msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);
        GetKeyNameText(msg, tmp, 0xFF);
        str = std::string(tmp);


    if (code == HC_ACTION && (wp == WM_SYSKEYDOWN || wp == WM_KEYDOWN )) {
        MessageBox(NULL,str.c_str(),NULL,MB_OK);
}
return CallNextHookEx(kbdhook, code, wp, lp);
}

LRESULT CALLBACK windowprocedure(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
    switch (msg) {
        case WM_CLOSE: case WM_DESTROY:
            running = false;
            break;
        default:
            /* Call default message handler */
            return DefWindowProc(hwnd, msg, wp, lp);
    }

    return 0;
}

int WINAPI WinMain(HINSTANCE thisinstance, HINSTANCE previnstance,
        LPSTR cmdline, int ncmdshow)
{


    HWND        hwnd;
    HWND        fgwindow = GetForegroundWindow(); 
    MSG     msg;
    WNDCLASSEX  windowclass;
    HINSTANCE   modulehandle;

    modulehandle = GetModuleHandle(NULL);
    kbdhook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)handlekeys, modulehandle, NULL);
    running = true;






    while (running) {

        if (!GetMessage(&msg, NULL, 0, 0))
            running = false; 
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

Right shift shows a blanco string in the alert. Left shift however shows a "SHIFT" string in the alert. Anyone a clue???

PS:

If I remove the line with " msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);" -> "RIGHT SHIFT" does show up now, but undefined shows up, when pressing the "Windows key"

user10056
  • 63
  • 4
  • 12
  • @paulm Right shift shows a blanco string in the alert. Left shift however shows a "SHIFT" string in the alert. – user10056 Sep 19 '13 at 17:38
  • 1
    It is a quirk in GetKeyNameText(). The shift keys are a bit special, they generate the same virtual keycode but have different scan codes. It just doesn't properly handle the scan code for the right shift key. You'll have to work around this limitation. – Hans Passant Sep 19 '13 at 17:55
  • @HansPassant Removing "msg += (st_hook.scanCode << 16);" turns other keys into blanco as well. – user10056 Sep 19 '13 at 18:19
  • @HansPassant However... If I remove the line with " msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);" -> "RIGHT SHIFT" does show up now, but undefined shows up, when pressing the "Windows key" – user10056 Sep 24 '13 at 21:28

2 Answers2

1

Left vs. right shift shows up in the vkCode field of KBDLLHOOKSTRUCT. You're using the key name of the scancode; the right shift key is named 'Shift', just like it says on the keyboard.

Apparently, right shift ends up with the extended flag set, which causes GetKeyNameText to look in the wrong table. Removing the extended flag ends up with a key name of "right shift".

    msg += (st_hook.scanCode << 16);
    if (st_hook.scanCode != 0x3a)
    {
        msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);
    }
    GetKeyNameText(msg, tmp, 0xFF);
Eric Brown
  • 13,774
  • 7
  • 30
  • 71
  • A "blanco" as in undefined character or as in the result is NULL. – user10056 Sep 24 '13 at 19:19
  • However... If I remove the lines related with "msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);" -> "RIGHT SHIFT" does show up now, but undefined shows up, when pressing the "Windows key" And it is mixind the up, left, right ,bottom arrows and 'insert', 'delete', 'end' up with numbers (1,2,3,4,5,6,7,8,9,0).... Btw. how do you know those Windows API things? – user10056 Sep 24 '13 at 21:27
  • @user10056 So the answer was to *specifically* ignore the extended flag for right shift (scan code 0x3a). The other keys (insert, delete, etc.) need the extended flag to get the correct behavior. I know these API things because I work on Windows. – Eric Brown Sep 24 '13 at 21:58
  • To be clear: "if (st_hook.scanCode != 0x3a){}" did not solve the problem. | "I work on Windows" <-- this statement is ambiguous... Do you mean the Windows kernel and the Windows APIs? – user10056 Sep 25 '13 at 00:08
  • 1
    It looks like my right shift is labeled with scancode "54" if (st_hook.scanCode != 54){} seems to work a bit better... But it shows "Alt Gr" as "ctrl+alt" somehow.. – user10056 Sep 25 '13 at 00:53
  • That's the fun with keyboard layouts. They're all different. Yes, I work on the Windows kernel and user-mode APIs. Alt-Gr *is* ctrl-alt, incidentally. – Eric Brown Sep 25 '13 at 01:13
1

This solution does not rely on a specific code

if (st_hook.vkCode != VK_RSHIFT)
  msg += ((st_hook.flags & LLKHF_EXTENDED) << 24);
Zombo
  • 1
  • 62
  • 391
  • 407