处理自定义QT小部件中的输入事件

Handle input events in custom Qt widget

本文关键字:输入 入事件 自定义 QT 小部 处理      更新时间:2023-10-16

我正在使用Visual Studio 2017中的游戏引擎库(AppGameKit(和QT(5.12.3(。通常使用此引擎的默认项目模板,将构建一个可执行的可执行文件,以启动它的可执行文件自己的窗口并处理钥匙和鼠标输入。

现在,我正在尝试调整以在QT中使用(嵌入在QWidget中(。目前,我通过将QWidgetHWND(QWidget::winId()(传递给游戏引擎初始化功能。

我现在唯一的问题是QT正在处理所有输入(鼠标和键盘(,我需要游戏引擎才能访问它。

通过检查游戏引擎的核心代码,我看到以下WndProc功能:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{        
    switch (message)
    {
        //Lots of input handling
        default:
        {
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    return 0;
}

游戏引擎中通常创建Win32窗口的代码执行以下操作(在我的情况下,这是我嵌入窗口小部件的情况下的(:

WNDCLASSEXW wcex;
wcex.cbSize         = sizeof(WNDCLASSEX);
wcex.style          = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc    = WndProc;
wcex.cbClsExtra     = 0;
wcex.cbWndExtra     = 0;
wcex.hInstance      = hInstance;
wcex.hIcon          = hIcon ? (HICON)hIcon : LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); 
wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName   = NULL;
wcex.lpszClassName  = L"OPENGLWINDOW";
wcex.hIconSm        = NULL;
RegisterClassExW(&wcex);

在某些时候创建窗口:

HWND hWnd = CreateWindowW(L"OPENGLWINDOW", L"AGK", dwStyle, x, y, 
            WindowRect.right-WindowRect.left, WindowRect.bottom-WindowRect.top, NULL, NULL, hInstance, NULL);

因此,我可以看到WndProc函数会发生什么,但是我不确定该如何将其"连接"到QT小部件。

一些谷歌搜索我也向我指出了qapplication :: installNativeEvent((,但在我的情况下如何使用它。

编辑

我尝试了installNativeEvent。因此,我将自己的QAbstractNativeEventFilter实施为:

class MyEventFilter : public QAbstractNativeEventFilter
{
public:
    MyEventFilter(){}
    bool nativeEventFilter(const QByteArray &eventType, void *message, long* res) override
    {
        if (eventType == "windows_generic_MSG") {
            res = (long*)WndProc(((MSG*)message)->hwnd, ((MSG*)message)->message, ((MSG*)message)->wParam, ((MSG*)message)->lParam);
        }
        return false;
    }
};

WndProc在游戏引擎中处理键和鼠标输入。

main.cpp

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    AGK_QT w;
    w.show();
    a.installNativeEventFilter(new MyEventFilter());
    return a.exec();
}

但我仍然没有从游戏引擎中的键盘或鼠标中得到任何响应。

问题中的 edit 部分是实际的正确答案。它起初没有工作,但这是因为一个不同的问题。

因此需要QAbstractNativeEventFilter

class MyEventFilter : public QAbstractNativeEventFilter
{
public:
    MyEventFilter(){}
    bool nativeEventFilter(const QByteArray &eventType, void *message, long* res) override
    {
        if (eventType == "windows_generic_MSG") {
            res = (long*)WndProc(((MSG*)message)->hwnd, ((MSG*)message)->message, ((MSG*)message)->wParam, ((MSG*)message)->lParam);
        }
        return false;
    }
};

WndProc在游戏引擎中处理键和鼠标输入。

main.cpp中,将事件过滤器设置为应用程序:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    AGK_QT w;
    w.show();
    a.installNativeEventFilter(new MyEventFilter());
    return a.exec();
} 

游戏引擎具有自己的循环,我需要致电:

 qApp->processEvents()

我的错误是在更新游戏引擎更新功能之前,我致电qApp->processEvents()。切换他们被称为我为我修复的顺序。