Hi All

I'm using SetWindowsHookEx to hook the keyboard. The connection is made and I am able to trap key presses. I'm also trying to call GetKeyboardState to obtain the state of the other keys at the time of the key press (to identify if shift, ctrl etc is pressed).

If I press the shift key, GetKeyboardState seems to return 0, then 1, and then when held down it tends to change between 128 and 129. I'm familiar with how to extract the state of the key from this value, however as it returns what appears to be rubbish, I'm at a loss for what to do.

The documentation for GetKeyboardState states:

An application can call this function to retrieve the current status of all the virtual keys. The status changes as a thread removes keyboard messages from its message queue. The status does not change as keyboard messages are posted to the thread's message queue, nor does it change as keyboard messages are posted to or retrieved from message queues of other threads.

So I'm thinking it could be some issue with the how the messages are posted, but I'm not too sharp on this.

Is anyone able to recommend how I can correctly use this function? Or another solution to what I am trying to achieve?

Here's the source code if it helps (using Qt):

.h

class SystemKeyboardReadWrite : public QObject
{

Q_OBJECT
public:
    // Returns singleton instance
    static SystemKeyboardReadWrite * instance();

    // Class destructor
    ~SystemKeyboardReadWrite();

    // Returns whether the keyboard hook is connected
    bool connected();

    // Connects / Disconnects the keyboard hook
    bool setConnected(bool state);

signals:
    // Broadcasts a key has been pressed
    void keyPressed(byte *keysDepressed, KeyId keyPressed);

public slots:

private:
    // Number of keys supported
    static const int numberKeys = 256;

    // Pointer to singleton instance
    static SystemKeyboardReadWrite *uniqueInstance;

    // Keyboard hook
    HHOOK keyboardHook;

    // Class constructor
    SystemKeyboardReadWrite();

    // Identifies hook activity
    static LRESULT CALLBACK keyboardProcedure(int nCode, WPARAM wParam, LPARAM lParam);

protected:

};

.cpp

SystemKeyboardReadWrite* SystemKeyboardReadWrite::uniqueInstance = 0;

SystemKeyboardReadWrite::SystemKeyboardReadWrite() :
    QObject()
{
    // Assign to null
    keyboardHook = NULL;
}

SystemKeyboardReadWrite::~SystemKeyboardReadWrite()
{
    delete uniqueInstance;
}

LRESULT CALLBACK SystemKeyboardReadWrite::keyboardProcedure(int nCode, WPARAM wParam, LPARAM lParam)
{
    // Check for a key down press
    if (nCode == HC_ACTION)
    {
        if (wParam == WM_KEYDOWN)
        {
            KBDLLHOOKSTRUCT *pKeyboard = (KBDLLHOOKSTRUCT*)lParam;

            byte *keysDepressed;

            keysDepressed = new byte[numberKeys];

            if(GetKeyboardState(keysDepressed))
            {
                // Broadcasts signal
                emit SystemKeyboardReadWrite::instance()->keyPressed(keysDepressed, (KeyId) pKeyboard->vkCode);               
            }

        }
        else if (wParam == WM_KEYUP)
        {

        }

    }

    return false;
}

bool SystemKeyboardReadWrite::connected()
{
    return keyboardHook;
}

bool SystemKeyboardReadWrite::setConnected(bool state)
{
    if(state && keyboardHook == NULL)
    {
        keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardProcedure, GetModuleHandle(NULL), 0);

        return keyboardHook;
    }
    else
    {
        UnhookWindowsHookEx(keyboardHook);
        keyboardHook = NULL;

        return keyboardHook;
    }
}

SystemKeyboardReadWrite* SystemKeyboardReadWrite::instance()
{
    if(uniqueInstance == NULL)
    {
        uniqueInstance = new SystemKeyboardReadWrite();
    }
    return uniqueInstance;

For any that encounter this problem, I found a solution by using this:

bool SystemKeyboardReadWrite::obtainKeyboard(BYTE* keys)
{
    bool result = false;

    HWND hwndActiveWin     = GetForegroundWindow();
    unsigned long idActive = GetWindowThreadProcessId(hwndActiveWin, NULL);
    HWND hwndFocused       = 0;

    if (AttachThreadInput(GetCurrentThreadId(), idActive, TRUE))
    {
        // Flushes previous keystate
        GetKeyState(0);

        result = GetKeyboardState(keys);   

        hwndFocused = GetFocus ();     
        AttachThreadInput(GetCurrentThreadId(), idActive, FALSE);
    }
    else
    {
        result = GetKeyboardState(keys);

        hwndFocused = hwndActiveWin;
    }

    return result;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.