Global hotkeys and nativeEvent() is not working in Qt6
-
I've made a small application (as seen on several examples) that registers a global hotkey with WINAPI's RegisterHotKey() function and handles the event in QWidget's reimplemented nativeEvent().
The application behaves as I expect when compiled with Qt versions 5.12.3 and 5.15.2; however, when I compile with 6.2.4 or 6.5.0 the nativeEvent() function is never called.
Is there some additional settings that I need to utilize when using Qt6?
GlobalHotKeyTest.h
#pragma once #include <QtWidgets/QMainWindow> #include "ui_GlobalHotkeyTest.h" #define HOTKEY_CTRL_ALT_S_ID 1 class GlobalHotkeyTest : public QMainWindow { Q_OBJECT public: GlobalHotkeyTest(QWidget *parent = nullptr); ~GlobalHotkeyTest(); protected: // The method for processing native events from the OS in Qt bool nativeEvent( const QByteArray& eventType, void* message, long* result ); private: Ui::GlobalHotkeyTestClass ui; };
GlobalHotkeyTest.cpp
#include "GlobalHotkeyTest.h" #include <windows.h> #include <QMessageBox> GlobalHotkeyTest::GlobalHotkeyTest(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); /*---------------------------------------------------------------- Windows Specific Register Ctrl+Alt+S as a hotkey combo. This registers the combo as a system-wide shortcut for this application so you can stop jiggling even when the application is not in the foreground. ----------------------------------------------------------------*/ bool result = RegisterHotKey( (HWND)this->window()->winId(), HOTKEY_CTRL_ALT_S_ID, MOD_CONTROL | MOD_ALT, Qt::Key_S ); if ( !result ) { DWORD error = GetLastError(); LPSTR messageBuffer = nullptr; //Ask Win32 to give us the string version of that message ID. //The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be). size_t size = FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPSTR)&messageBuffer, 0, NULL ); //Copy the error message into a std::string. std::string message( messageBuffer, size ); //Free the Win32's string's buffer. LocalFree( messageBuffer ); QMessageBox::critical( this, "Failed to register hot key", QString::fromStdString( message ) ); }; } GlobalHotkeyTest::~GlobalHotkeyTest() { UnregisterHotKey( (HWND)this->window()->winId(), HOTKEY_CTRL_ALT_S_ID ); } bool GlobalHotkeyTest::nativeEvent( const QByteArray & eventType, void* message, long* result ) { /*---------------------------------------------------------------- Windows Specific Intercept the hotkey message from the windows event filter. // ----------------------------------------------------------------*/ MSG* msg = static_cast<MSG*>( message ); if ( msg->message == WM_HOTKEY ) { LPARAM combo = Qt::Key_S << 16 | MOD_CONTROL | MOD_ALT; bool result = msg->lParam & combo; QMessageBox::information(this,"Hotkey detected","The hotkey was detected"); return( true ); } return( false ); }
-
Hi, the function declaration of nativeEvent() has changed slightly in Qt6 so it will work again if you change:
// Qt5 flavor bool nativeEvent( const QByteArray& eventType, void* message, long* result );
to
// Qt6 flavor bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result);
P.S Actually why not add the override spec. so you're prepared for Qt7 (if that had been in there in Qt5 you would got a compiler error today :-)
// preparing for Qt7 or later bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
-
-
@hskoglund Thanks for the pointing that out. I guess I did not pay close enough attention to the new declaration.