How do I use QKeyEvent::key() even if window is not on top?
-
Hello there,
I've been developing a sort of code manager where functions are set and activated by hex codes (It's pretty much an esoteric programming language with an actual use lol).
Right now I'm coding a function to check if a certain key is pressed in order to enable the following instruction(s).
i can already get the current key's value when the window is on top. But it stops working as soon as I leave the window.
I need it to be active while I'm outside the window or in the actual game.For testing purposes I'd like to get this code running while the window is not on top.
void MainWindow::keyPressEvent(QKeyEvent *ckey) { ui->label->setText(QString::number(ckey->key(), 16) + " " + ckey->text() + " " + QString::number(ckey->nativeScanCode(), 16)); }
The application also has a QTimer that is permanently active even if the window is not on top. Maybe this can be used as a reference point here...
Would anyone like to help me?
Thanks -
@SnuggleKat said in How do I use QKeyEvent::key() even if window is not on top?:
I need it to be active while I'm outside the window or in the actual game.
then Qt is not the right framework for you.
By definition only the active GUI window gets the input events delivered.You need to hook into the OS using native API to achieve what you want.
-
Hi @SnuggleKat
What if you install an eventFilter ?
There is an example in the link:
class KeyPressEater : public QObject { Q_OBJECT ... protected: bool eventFilter(QObject *obj, QEvent *event); }; bool KeyPressEater::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); qDebug("Ate key press %d", keyEvent->key()); return true; } else { // standard event processing return QObject::eventFilter(obj, event); } }
And here's how to install it on two widgets:
KeyPressEater *keyPressEater = new KeyPressEater(this); QPushButton *pushButton = new QPushButton(this); QListView *listView = new QListView(this); pushButton->installEventFilter(keyPressEater); listView->installEventFilter(keyPressEater);
-
@raven-worx said in How do I use QKeyEvent::key() even if window is not on top?:
then Qt is not the right framework for you.
By definition only the active GUI window gets the input events delivered.You need to hook into the OS using native API to achieve what you want.
I think there is a way to achieve this with Qt (and an API) since there is other programs developed with Qt that allow "Background Input" (e.g. Dolphin Emulator).
I'm checking out Microsoft's API Documentation right now but I'm uncertain which Function is the right one: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645530(v=vs.85).aspx
-
@SnuggleKat said in How do I use QKeyEvent::key() even if window is not on top?:
I think there is a way to achieve this with Qt (and an API)
thats what i said...
Qt alone isn't capable of it. As i said you need to use native API to get the key events.
Of course you can create artificial events at any time and inject them into Qt's event-loop. -
Hi
it sounds like you want a global hot key
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646309(v=vs.85).aspx -
@mrjj said in How do I use QKeyEvent::key() even if window is not on top?:
Hi
it sounds like you want a global hot key
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646309(v=vs.85).aspxThis looks like what I need. Thanks!
Using this results in 2 error messages:- mainwindow.obj:-1: Fehler: LNK2019: unresolved external symbol __imp_RegisterHotKey referenced in function "public: void __cdecl MainWindow::timer(void)" (?timer@MainWindow@@QEAAXXZ) - debug\Code_Manager.exe:-1: Fehler: LNK1120: 1 unresolved externals
I have tried checking whether the b-key is pressed:
if (RegisterHotKey(NULL, 1, MOD_ALT | MOD_NOREPEAT, 0x42) == TRUE) //0x42 is 'b' { ui->label->setText("true"); } else { ui->label->setText("false"); }
-
@SnuggleKat
Hi
The trick is always check which library to link to
Then add
LIBS += -luser32
to the .pro file.
-
@mrjj said in How do I use QKeyEvent::key() even if window is not on top?:
LIBS += -luser32
Thanks, but the problem still remains the same
-
@SnuggleKat
Remember to run qmake after adding it
Up in the build menu. -
@mrjj said in How do I use QKeyEvent::key() even if window is not on top?:
@SnuggleKat
Remember to run qmake after adding it
Up in the build menu.Thanks. I could compile it now. But the key value doesn't get checked. Could this issue be caused by the function being inside called up by a QTimer?
If I put the function into the MainWindow::MainWindow the RegisterHotKey permanently returns TRUE -
Hi
You mean from a timer slot ?
Should not make a difference however if you call it multiple times t without -
UnregisterHotKey , it might considered it already registered and return false.
you can show what GetLastError says in that case. -
@mrjj said in How do I use QKeyEvent::key() even if window is not on top?:
Hi
You mean from a timer slot ?
Should not make a difference however if you call it multiple times t without -
UnregisterHotKey , it might considered it already registered and return false.
you can show what GetLastError says in that case.Well, I got it working while the window is on top. But once I leave the window the button isn't registered anymore.
RegisterHotKey(NULL, 0, MOD_IGNORE_ALL_MODIFIER, 0x42); MSG msg; GetMessage(&msg, 0, 0, 0); PeekMessage(&msg, 0, 0, 0, 0x0001); if(msg.wParam == 0x42) //0x42 is 'b' { ui->label->setText("true"); *(cheat_array + 16) = 0x11; } else { ui->label->setText("false"); *(cheat_array + 16) = 0x00; }
-
Hi
You are using NULL for windows handle
Docs says
"If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread and must be processed in the message loop."So i am wondering if it gets delivered by Qt when its not active.
Try to use its
(HWND)winId();
instead of NULL -
-
@SnuggleKat
Ok, i think its related to how the events are sent when windows not
in focus.try use eventfilter for native events and see if it comes there when not in focus.
https://forum.qt.io/topic/32640/help-with-qabstractnativeeventfilteryou can also try this sample ( non qt) and see if that works in all cases.
Its uses native msg pump.#include <stdio.h> #include <tchar.h> #include <windows.h> int main() { enum{ONE_KEYID = 1, TWO_KEYID = 2}; RegisterHotKey(0, ONE_KEYID, MOD_NOREPEAT, 0x31); // register 1 key as hotkey RegisterHotKey(0, TWO_KEYID, MOD_NOREPEAT, 0x32); // register 2 key as hotkey MSG msg; while(GetMessage(&msg, 0, 0, 0)) { PeekMessage(&msg, 0, 0, 0, 0x0001); switch(msg.message) { case WM_HOTKEY: if(msg.wParam == ONE_KEYID) { printf("1 Pressed"); } else if(msg.wParam == TWO_KEYID) { printf("2 Pressed"); } } } return 0; }
-
@mrjj said in How do I use QKeyEvent::key() even if window is not on top?:
@SnuggleKat
Ok, i think its related to how the events are sent when windows not
in focus.try use eventfilter for native events and see if it comes there when not in focus.
https://forum.qt.io/topic/32640/help-with-qabstractnativeeventfilteryou can also try this sample ( non qt) and see if that works in all cases.
Its uses native msg pump.#include <stdio.h> #includ...
My recent code update was based on this example.
Tried rebuilding it but didn't work either.And I'm a little bit lost about the EventFilter thing..
-
The link have sample of such eventfiler.
its not much code.Its odd, the other sample didnt work as its windows less and have message pump.
But if u mix with a normal Qt it makes sense as the events are eating by QApplication then. -
@mrjj said in How do I use QKeyEvent::key() even if window is not on top?:
The link have sample of such eventfiler.
its not much code.Its odd, the other sample didnt work as its windows less and have message pump.
But if u mix with a normal Qt it makes sense as the events are eating by QApplication then.I'm sorry, I can't get it to compile..
Could it be it doesn't work because the timer() function is a (public) slot?
-
@SnuggleKat
A slot is just a normal c++ function.But i dont understand why you need to call it in a timer.
You normally call it ONLY once to set up hot key.
Then reacts to WM_HOTKEY native event.
There would be no need of a timer.Mixing Qt application and GetMessage() might have side effects.
This might help
http://amin-ahmadi.com/2015/11/14/how-to-use-system-wide-hotkeys-in-your-qt-application/