I'm trying to replicate QKeyEvents
sent on a QWidget
to another non-Qt Window, for this, I'm using the WINAPI PostMessage
together WM_KEYDOWN / WM_KEYUP
messages
Based on this stack answer
and Microsoft documentation of Keystroke Message Flags
I wrote this small compilable example:
//mainwindow.h
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindowClass; };
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
bool eventFilter(QObject* obj, QEvent* event);
protected:
virtual bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
private:
Ui::MainWindowClass *ui;
};
// mainwindow.cpp
#include "MainWindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindowClass())
{
ui->setupUi(this);
QTextEdit* textEdit = new QTextEdit(this);
textEdit->installEventFilter(this);
textEdit->setGeometry(50, 50, 200, 50);
}
bool MainWindow::eventFilter(QObject* obj, QEvent* event)
{
switch (event->type())
{
case QEvent::KeyPress:
case QEvent::KeyRelease:
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
WPARAM wParam = keyEvent->nativeVirtualKey();
bool keyRelease = keyEvent->type() == QEvent::KeyRelease;
LPARAM lParam = 0;
lParam |= (keyRelease) ? (1 << 31): (0); // Transition state
lParam |= (keyEvent->isAutoRepeat() || keyRelease) ? (1 << 30) : 0; // Previous key state
lParam |= (keyEvent->modifiers() & Qt::AltModifier) ? (1 << 29) : 0;
bool isExtendedKey = (keyEvent->nativeScanCode() & 0x0100) != 0; // Extended key
lParam |= (isExtendedKey ? (1 << 24) : 0);
lParam |= (keyEvent->nativeScanCode() << 16); // Scan code
lParam |= 1; // Repeat count
// Just for debugging:
WORD keyFlags = HIWORD(lParam);
WORD scanCode = LOBYTE(keyFlags); // scan code
qDebug() << (keyRelease ? "[[KEYUP]]" : "[[KEYDOWN]]")
<< "\nwParam" << wParam << "lParam" << lParam
<< "\nscanCode" << scanCode << "\n";
//PostMessage(hwnd, keyEvent->type() == QEvent::KeyPress ? WM_KEYDOWN : WM_KEYUP, wParam, lParam);
}
}
return false;
}
bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr* result)
{
MSG* msg = static_cast<MSG*>(message);
switch (msg->message)
{
case WM_KEYDOWN:
case WM_KEYUP:
{
WORD keyFlags = HIWORD(msg->lParam);
WORD scanCode = LOBYTE(keyFlags); // scan code
qDebug() << (msg->message == WM_KEYDOWN ? "KEYDOWN" : "KEYUP")
<< "\nwParam" << msg->wParam << "lParam" << msg->lParam
<< "\nscanCode:" << scanCode;
break;
}
default:
break;
}
return QWidget::nativeEvent(eventType, message, result);
}
The lParam
from the nativeEvent
(window procedure) is different from the one I'm building inside the eventFilter
, trying to figure out what I'm calculating wrong.
When I input a
in the textEdit this is what I get:
KEYDOWN
wParam 65 lParam 1966081
scanCode: 30
[[KEYDOWN]]
wParam 65 lParam 1966081
scanCode 30
KEYUP
wParam 65 lParam 3223191553
scanCode: 30
[[KEYUP]]
wParam 65 lParam -1071775743
scanCode 30