我如何在Win32控制台应用程序中注册一个不可见的窗口类?

问题描述 投票:0回答:1

我正在尝试在Win32控制台应用程序中注册一个不可见的窗口。我的目标是在WindowProc中监听原始输入,以(1)在控制台上显示它,以及(2)执行其他计算,例如通过Web套接字发送信息。我关注了this CodeProject article,但是我的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);
        }
    }
}

我的WindowProc功能:

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

我有一个基于this article的类似实现,其中注册成功,但是我无法收听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);
            }
        }
    }
}

我想理想地注册该类并在控制台上显示原始输入(方法1),但是能够执行方法2的修改也可以。

为什么我的注册方法1失败?为什么在方法2中我无法收听WM_INPUT消息?

c++ windows winapi console raw-input
1个回答
0
投票

方法1:

您需要初始化wndclass

WNDCLASSEX wndclass = { 0 };

否则,未初始化的部分默认为随机值(未定义的行为,通常类似于0xcccccccc,并且RegisterClassEx将失败,错误代码:87。

方法2:

您初始化了wndclass中的所有成员,因此RegisterClassEx成功。我无法重现方法2的问题,问题可能出在registerTouchpadForInput中。

注意到此函数没有参数,但是RegisterRawInputDevices需要设置RAWINPUTDEVICE.hwndTarget,也许您没有设置目标窗口,如果您设置为NULL,则根据document,您必须将键盘聚焦在窗口以接收消息。

此外,在方法2中,程序将创建一个可见窗口。要生成不可见的窗口,请像方法1一样创建一个Message-Only Windows

样本:

#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);
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.