Обрабатывать события ввода в пользовательском виджете Qt - PullRequest
0 голосов
/ 25 мая 2019

Я использую библиотеку игрового движка (AppGameKit) и Qt (5.12.3) в Visual Studio 2017. Обычно при использовании шаблона проекта по умолчанию этого движка создается исполняемый файл, который запускает собственное окно и обрабатывает ввод с помощью клавиш и мыши. .

Теперь я пытаюсь настроить это для использования в Qt (встроено в QWidget). На данный момент мне удалось сделать это, передав HWND из QWidget (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 () но не совсем понятно, как использовать его в моем случае.

EDIT

Я пытался с 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();
}

Но я все еще не получаю ответа от клавиатуры или мыши в игровом движке.

1 Ответ

0 голосов
/ 25 мая 2019

Раздел РЕДАКТИРОВАТЬ в вопросе является правильным ответом. Сначала это не работало, но это было из-за другой проблемы.

Так что 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() перед обновлением функции обновления игрового движка. Смена порядка, который они называли, исправила это для меня.

...