как мне зарегистрировать невидимый оконный класс в консольном приложении Win32? - PullRequest
0 голосов
/ 29 мая 2020

Я пытаюсь зарегистрировать невидимое окно в консольном приложении Win32. Моя цель - прослушать Raw Input в WindowPro c, чтобы (1) отобразить его на консоли и (2) выполнить дополнительные вычисления, например, отправить информацию через веб-сокет. Я следил за этой статьей CodeProject , но моя WNDCLASSEX регистрация кажется неудачной.

Вот код, который у меня есть:

подход 1 - регистрация не кажется для работы

Моя основная функция

WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.lpfnWndProc = NVTouch_WindowProc;
wndclass.hInstance = GetModuleHandle(NULL);
wndclass.lpszClassName = L"myclass";
bool isClassRegistered = false;
isClassRegistered =  RegisterClassEx(&wndclass);
if (isClassRegistered) //1
{
    HWND window = CreateWindow(wndclass.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(0), NULL);
    if (window)
    {
        ShowWindow(window, SW_SHOWDEFAULT);
        MSG msg;
        while (GetMessage(&msg, 0, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
}

Моя функция WindowPro c:

static LRESULT CALLBACK NVTouch_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    std::cout << "window Proc";
    bool registrationStatus = false;
    switch (message)
    {
    case WM_CREATE:
        registrationStatus  = registerTouchpadForInput();
        break;
    case WM_DESTROY:
        std::cout << "destroying application.";
        PostQuitMessage(0);
        break;
    case WM_INPUT:
        std::cout << "input!";
        break;
    default:
        std::cout << "default.";
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

Когда я устанавливаю точки останова в Visual Studio 2019, я замечаю скачки кода от //1 до //2 со статусом регистрации false.

У меня была аналогичная реализация на основе этой статьи , где регистрация прошла успешно, но я не смог прослушивать сообщения WM_INPUT.

подход 2 - создание окна работает, но сообщения WM_INPUT не читаются

int main()
{
    WNDCLASSEX wndclass = {
        sizeof(WNDCLASSEX),
        CS_DBLCLKS,
        NVTouch_WindowProc,
        0,
        0,
        GetModuleHandle(0),
        LoadIcon(0,IDI_APPLICATION),
        LoadCursor(0,IDC_ARROW),
        HBRUSH(COLOR_WINDOW + 1),
        0,
        L"myclass",
        LoadIcon(0,IDI_APPLICATION)
    };
    bool isClassRegistered = false;
    isClassRegistered =  RegisterClassEx(&wndclass);
    if (isClassRegistered)
    {
        std::cout << "window class registered!";
        HWND window = CreateWindowEx(0, L"myclass", L"title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
        if (window)
        {
            ShowWindow(window, SW_SHOWDEFAULT);
            MSG msg;
            while (GetMessage(&msg, 0, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }
}

Я хочу идеально зарегистрировать класс и отобразить Raw Input на console (подход 1), но возможность выполнить этот модифицирующий код подхода 2 также будет работать.

Почему моя регистрация не выполняется в подходе 1? Почему я не могу прослушивать сообщения WM_INPUT в подходе 2?

1 Ответ

0 голосов
/ 01 июня 2020

В подходе 1:

Вам необходимо инициализировать wndclass:

WNDCLASSEX wndclass = { 0 };

В противном случае неинициализированная часть по умолчанию принимает случайные значения (поведение Undefined, обычно как 0xcccccccc), и RegisterClassEx завершится ошибкой с кодом: 87.

В подходе 2:

Вы инициализировали все элементы в wndclass, поэтому RegisterClassEx завершится успешно. Я не могу воспроизвести проблему с подходом 2. Проблема может быть в registerTouchpadForInput.

Заметил, что эта функция не имеет параметров, но RegisterRawInputDevices нужно установить RAWINPUTDEVICE.hwndTarget, возможно, вы не установили целевое окно, если вы установите значение NULL, в соответствии с документом , вы должны сфокусировать клавиатуру на своем окне, чтобы получить сообщение.

Кроме того, в подходе 2 программа создаст видимое окно. Для создания невидимого окна создайте Только сообщение Windows, как в подходе 1.

образец:

#include <windows.h>
#include <iostream>

using namespace std;
BOOL registerTouchpadForInput(HWND hWnd)
{
    RAWINPUTDEVICE rid;
    rid.dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;
    rid.usUsagePage = 1;                            // raw keyboard data only
    rid.usUsage = 6;
    rid.hwndTarget = hWnd;
    return RegisterRawInputDevices(&rid, 1, sizeof(rid));
}
static LRESULT CALLBACK NVTouch_WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    std::cout << "window Proc";
    BOOL  registrationStatus = false;
    switch (message)
    {
    case WM_CREATE:
        registrationStatus = registerTouchpadForInput(hwnd);
        break;
    case WM_DESTROY:
        std::cout << "destroying application.";
        PostQuitMessage(0);
        break;
    case WM_INPUT:
        std::cout << "input!";
        return DefWindowProc(hwnd, message, wParam, lParam);
    default:
        std::cout << "default.";
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

int main()
{
    WNDCLASSEX wndclass = {
        sizeof(WNDCLASSEX),
        CS_DBLCLKS,
        NVTouch_WindowProc,
        0,
        0,
        GetModuleHandle(0),
        LoadIcon(0,IDI_APPLICATION),
        LoadCursor(0,IDC_ARROW),
        HBRUSH(COLOR_WINDOW + 1),
        0,
        L"myclass",
        LoadIcon(0,IDI_APPLICATION)
    };
    bool isClassRegistered = false;
    isClassRegistered = RegisterClassEx(&wndclass);
    if (isClassRegistered)
    {
        std::cout << "window class registered!";
        //HWND window = CreateWindowEx(0, L"myclass", L"title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
        HWND window = CreateWindow(wndclass.lpszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(0), NULL);
        if (window)
        {
            ShowWindow(window, SW_SHOWDEFAULT);
            MSG msg;
            while (GetMessage(&msg, 0, 0, 0))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...