c++ - SetCapture 不起作用并返回 nullptr

标签 c++ winapi

我正在尝试为窗口游戏捕获鼠标以处理鼠标输入,但每次我尝试时,它都会返回 nullptr。我在窗口上看到的是一个等待光标(蓝色圆圈)。

这是 Win32 窗口包装器的代码:

XWindow::XWindow(WCHAR* title, int width, int height)
{
     memcpy(m_szTitle, title, sizeof(title));
     m_width = width;
     m_height = height;
}

ATOM XWindow::MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, 
    MAKEINTRESOURCE(IDI_WIN32PROJECT1));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName = nullptr;
    wcex.lpszClassName  = m_szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, 
    MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

BOOL XWindow::InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    m_hInst = hInstance; 
    m_hWnd = CreateWindowW(m_szWindowClass, m_szTitle, WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, 0, m_width, m_height, nullptr, nullptr, hInstance, nullptr);

    if (!m_hWnd)
        return FALSE;

    ShowWindow(m_hWnd, nCmdShow);
    UpdateWindow(m_hWnd);

    return TRUE;
}


LRESULT CALLBACK XWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            switch (wmId)
            {
                case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
                default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);

            EndPaint(hWnd, &ps);
        }
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
}

这是 WinMain 函数:

int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE 
hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
    XIllumin* pMainGameWindow = new XIllumin(L"X3DEngine", 800, 600);

    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    if (LoadStringW(hInstance, IDS_APP_TITLE, pMainGameWindow-
    >GetWindowTitle(), MAX_LOADSTRING) == 0)
    return FALSE;

    if (LoadStringW(hInstance, IDC_WIN32PROJECT1, pMainGameWindow-
    >GetWindowClass(), MAX_LOADSTRING) == 0)
    return FALSE;

    pMainGameWindow->MyRegisterClass(hInstance);

    if (!pMainGameWindow->InitInstance(hInstance, nCmdShow))
        return FALSE;

    if (SetCapture(pMainGameWindow->GetWindowHandle()) == nullptr)
    //  return FALSE;

    if (!pMainGameWindow->ParseInitFile("Config/GameInit.txt"))
    {
        pMainGameWindow->FAIL_MSG_BOX(L"Error loading init file.");
        return FALSE;
    }

    pMainGameWindow->InitGameObjects(" ");

    HACCEL hAccelTable = LoadAccelerators(hInstance, 
    MAKEINTRESOURCE(IDC_WIN32PROJECT1));

    MSG msg;

    while (1)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
            {
                 pMainGameWindow->CleanUp();
                 break;
            }

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if (!pMainGameWindow->GameMain(" "))
            break;
    }

    return (int)msg.wParam;
}

我不确定到底哪里出了问题。我认为它可能是 CreateWindowW() 的窗口创建参数,但真的不知道该使用哪个。

编辑:当我将鼠标光标悬停在游戏窗口上时,输入应该由游戏窗口处理,但是一旦窗口弹出并且光标悬停在上面,我就会看到一个等待光标。不太确定除此之外还能说些什么。

最佳答案

请注意,SetCapture 返回先前捕获鼠标的窗口的句柄。因此,当鼠标先前未被其他窗口捕获时,SetCapture 返回 NULL 是可以的。 “等待”光标与它无关。

请注意,通过注释 //return FALSE; 您将 if 范围更改为以下内容,可能会跳过配置加载:

if (SetCapture(pMainGameWindow->GetWindowHandle()) == nullptr)
{
    //  return FALSE;

    if (!pMainGameWindow->ParseInitFile("Config/GameInit.txt"))
    {
        pMainGameWindow->FAIL_MSG_BOX(L"Error loading init file.");
        return FALSE;
    }
}

这是一个很好的例子,说明为什么永远不应省略 {}

您应该在调用 SetCapture 之前发送消息,这样窗口就会被初始化并正确地进入前台:

// at InitInstance
UpdateWindow(m_hWnd);
MSG msg;
while(PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
{
       TranslateMessage(&msg);
       DispatchMessageW(&msg);
}

关于c++ - SetCapture 不起作用并返回 nullptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47080640/

相关文章:

c++ - 无模板优化

c++ - cout << std::ios::hex 是做什么的?

c++ - 跨平台文件结构处理

c++ - 帧限制器 |为什么会有额外的毫秒?

windows - Windows 编程中的 _spawnl 和 Createprocess(...) API 有什么区别?

c++ - 从函数返回堆字符指针的问题

c++ - DialogBox 消息是否发送到自定义消息循环?

windows - 操作系统不会关闭,但我的应用程序会

c++ - 为什么我的 DwmExtendFrameIntoClientArea() 窗口没有绘制 DWM 边框?

应用程序接口(interface) |注销 RawInputDevice