鼠标输入未从其他进程的窗口释放

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

我正在编写一个 C++ Windows 程序,它使用 Win32 窗口和 DirectX11 渲染器显示游戏的游戏统计信息/好友信息。 (呈现一个用鼠标和键盘控制的用户界面)

窗口覆盖在游戏窗口的顶部,并设置了标志 WS_EX_TRANSPARENTWS_POPUP。 当窗口被激活时,我设置 WS_EX_LAYERED 来捕获输入。

如果GetWindow(target_, GW_HWNDPREV) 与创建窗口的句柄不同,则创建窗口位于目标窗口之上。 通过使用 SWP_NOACTIVATE | 调用 SetWindowPos 将其放置在其之上。 SWP_NOMOVE | SWP_NOSIZE | SWP_ASYNCWINDOWPOS.

我已经仔细检查了标志设置是否正确以及函数是否被调用。 我也尝试使用带有 SW_SHOW 标志的 ShowWindow,但结果保持不变。

我目前正在 Portal 2 上运行我的测试,但理想情况下,我希望它适用于大多数游戏。 (使用的操作系统是Windows 11 22H2)

为了激活窗口并从游戏中释放鼠标捕获,我调用了 SetForegroundWindow、SetActiveWindow 和 SetFocus,所有这些都带有我窗口的 HWND。 当我从 Visual Studio 运行程序时,这种方法工作正常,但是当我运行编译后的可执行文件时,鼠标在游戏中保持锁定状态。

两个版本都在调试和发布模式下进行了测试,我真的不明白为什么会这样。

LRESULT Renderer::WndProc(...) {
    switch (message) {
    case WM_SIZE:
        // resize buffers and recreate render target view
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(handle, message, w_param, l_param);
}

bool Window::Create(...) {
    // ...
    hwnd_ = CreateWindowEx(
        wndclass,
        class_name_.c_str(),
        title_.c_str(),
        WS_POPUP,
        0, 0, 10, 10,
        nullptr,
        nullptr,
        nullptr,
        nullptr
    );

    SetLayeredWindowAttributes(hwnd_, 0, 255, LWA_ALPHA);
    UpdateWindow(hwnd_);

    constexpr MARGINS margin = {-1, -1, -1, -1};
    const auto result = DwmExtendFrameIntoClientArea(hwnd_, &margin);
    
    // ...
}

void Window::Activate() {
    // Remove the WS_EX_LAYERED attribute.
    SetClickThrough(false);

    SetForegroundWindow(hwnd_);
    SetActiveWindow(hwnd_);
    SetFocus(hwnd_);
}

// ----------------------
// Sample main routine pseudocode:
// ----------------------

renderer->window.Create(...);
while (renderer->is_running()) {
    renderer->BeginFrame();

    // Position the window on top of the game found.
    renderer->window().FollowTarget();

    // Toggle the visibility using the F2 key.
    // If transitioning from hidden to visible, call the window
    // activation routine.
    if (utils::KeyPressed(VK_F2)) {
        if (ui->is_visible()) {
            // .. window deactivation not included
            ui->set_visible(false);
        }
        else {
            renderer->window().Activate();
            ui->set_visible(true);
        }
    }   

    ui->Draw(renderer);
    renderer->Present();
}

我考虑过使用低级键盘/鼠标钩子来捕获输入,或使用 DirectX 钩子进行屏幕外渲染并在游戏中呈现它,但我宁愿避免使用它,因为它需要许多游戏手动将其列入白名单。

还有什么我想念的或者我应该采取不同的方法吗?

c++ windows winapi overlay
© www.soinside.com 2019 - 2024. All rights reserved.