C++ Win32 Keyboard Events

C++/Win32: Keyboard input to a non-foreground window

You can use SetWindowsHookEx with WH_KEYBOARD_LL parameter:

Here is a sample:

#include <windows.h>
#include <iostream>
HHOOK _k_hook;
LRESULT __stdcall k_Callback1(int nCode, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT key = (PKBDLLHOOKSTRUCT)lParam;
//a key was pressed
if (wParam == WM_KEYDOWN && nCode == HC_ACTION)
{
switch (key->vkCode)
{
case VK_ESCAPE:
puts("ESC pressed");
break;
case 'A':
puts("A pressed");
break;
case VK_RETURN:
puts("RETURN pressed");
break;
}
}

return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int main()
{
_k_hook = SetWindowsHookEx(WH_KEYBOARD_LL, k_Callback1, NULL, 0);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) != 0)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
if (_k_hook)
UnhookWindowsHookEx(_k_hook);
return TRUE;
}

It works as follows:

Sample Image

Keyboard Input & the Win32 message loop

Use char c = MapVirtualKey(param,MAPVK_VK_TO_CHAR); to convert virtual key codes to char, and process WM_KEYUP and WM_KEYDOWN and their wParams.

if (PeekMessage (&mssg, hwnd, 0, 0, PM_REMOVE))
{
switch (mssg.message)
{
case WM_QUIT:
PostQuitMessage (0);
notdone = false;
quit = true;
break;

case WM_KEYDOWN:
WPARAM param = mssg.wParam;
char c = MapVirtualKey (param, MAPVK_VK_TO_CHAR);
this->p->Input ()->Keyboard ()->Listeners ()->OnKeyDown (c);
break;

case WM_KEYUP:
WPARAM param = mssg.wParam;
char c = MapVirtualKey (param, MAPVK_VK_TO_CHAR);
this->p->Input ()->Keyboard ()->Listeners ()->OnKeyUp (c);
break;
}
// dispatch the message
TranslateMessage (&mssg);
DispatchMessage (&mssg);
}

Managing keyboard events between Win32 app and QWinMigrate

I have no idea if this will actually work but you might give this a go:

class KeyEventPropagetionPreventer: public QObject
{
public:
KeyEventPropagetionPreventer( QWidget * widget )
: QObject( widget ), widget( widget ), instercept_events( true )
{
widget->installEventFilter( this )
}

bool eventFilter(QObject *obj, QEvent *event)
{
if ( intercept_events && event->type() == QEvent::KeyPress) // or other types if needed
{
intercept_events = false; // prevents eating your own events
QKeyEvent new_event( *event ); // Might be that you need to implement your own copying function if the copyconstructor is disabled
QApplication::sendEvent(this->widget, &new_event);
instercept_events = true;
return true;
}
else
{
return QObject::eventFilter(obj, event);
}
}

private:
QWidget * widget;
bool instercept_events;
}

Then you add this line where you create the dialog:

new KeyEventPropagetionPreventer( your_qt_dialog ); // will be deleted by the Qt parent/child system when the dialog is deleted.

The idea is to intercept all Keyboard events, but then also create a copy of it and send that to the widget. Hopefully the intercepting actually prevents the event from propagating (and is not qt-eventsystem-only or something) and the QApplication::sendEvent() does not propagate itself.

I hope this works, good luck!

(ps. This code has not been tested or compiled)

Win32 Keyboard combination

You should use the GetKeyState function during the processing of WM_SYSKEYDOWN messages.

case WM_SYSKEYDOWN:
{
if ( GetKeyState ( VK_MENU ) < 0 && GetKeyState ( VK_UP ) < 0 )
{

}
}

Possible to Tie Keyboard Input to a Single Application in Win32?

After some additional testing, blocking with a WH_KEYBOARD hook was only partially reliable. It did not work with the newer-style Windows Store applications or higher-level ones, even after moving the DLL and adjusting the permissions as I have read from others. Furthermore, it would often miss out or get duplicate hook messages depending on what I was trying to do.

WH_KEYBOARD_LL was more reliable, but it could not be used because it came before the raw input messages which identified the device.

I've come to the conclusion that the only reliable way to do this is through low-level driver/kernel programming. That's a completely different can of worms, and I'm not going to look for a can opener.

How to send hardware level keyboard input by program?

I once used SendInput to control a game character. Game (icy tower?) was using directx input system (I think?) and somehow it was ignoring keybd_event calls but this method worked. I do not know how close to hardware you need to be but did this the trick for me. I used virtual key codes but turned them into scancodes for this answer.

UINT PressKeyScan(WORD scanCode)
{
INPUT input[1] = {0};
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = NULL;
input[0].ki.wScan = scanCode;
input[0].ki.dwFlags = KEYEVENTF_SCANCODE;

UINT ret = SendInput(1, input, sizeof(INPUT));

return ret;
}

UINT ReleaseKeyScan(WORD scanCode)
{
INPUT input[1] = {0};
input[0].type = INPUT_KEYBOARD;
input[0].ki.wVk = NULL;
input[0].ki.wScan = scanCode;
input[0].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;

UINT ret = SendInput(1, input, sizeof(INPUT));

return ret;
}

To simulate press and release you use them sequentially (or you may create a separate function for press and release that use same INPUT structure).

WORD scanCodeSpace = 0x39;
PressKeyScan(scanCodeSpace);
ReleaseKeyScan(scanCodeSpace)

You can use MapVirtualKeyA to get scan code from virtual key code.



Related Topics



Leave a reply



Submit