You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用cl.exe编译游戏宏程序触发双显示器关闭的问题求助

cl.exe编译游戏宏程序触发显示器关闭问题排查与解决

我正在开发一款游戏宏程序,仅在使用cl.exe编译时,按下宏启用按键会导致笔记本屏幕和HDMI外接显示器同时关闭;用g++编译则完全正常。我希望保留cl.exe编译方式,避免用户额外安装MinGW。

已尝试的操作:

  • 移除鉴权代码(问题最初是添加鉴权后出现,但移除后仍未解决)
  • 注释功能模块,问题依旧存在

核心代码片段

虚拟按键/鼠标模拟函数

// 虚拟按键模拟(宏核心驱动)
// 模拟按键按下
void PressKey(int key)
{
    INPUT input;
    input.type = INPUT_KEYBOARD;
    input.ki.wScan = MapVirtualKey(key, MAPVK_VK_TO_VSC);
    input.ki.time = 0;
    input.ki.dwExtraInfo = 0;
    input.ki.wVk = key;
    input.ki.dwFlags = 0;
    SendInput(1, &input, sizeof(INPUT));

    // 释放按键
    input.ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(1, &input, sizeof(INPUT));
}

// 模拟鼠标点击
void SimulateMouseClick(bool isRight = true)
{
    INPUT input;
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = isRight ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN;
    SendInput(1, &input, sizeof(INPUT));

    input.mi.dwFlags = isRight ? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP;
    SendInput(1, &input, sizeof(INPUT));
}

// 相对移动鼠标
void MoveMouse(int dx, int dy)
{
    INPUT input;
    input.type = INPUT_MOUSE;
    input.mi.dx = dx;
    input.mi.dy = dy;
    input.mi.dwFlags = MOUSEEVENTF_MOVE;
    SendInput(1, &input, sizeof(INPUT));
}

主函数与消息循环

// 主函数与循环
int main()
{
    // Auth::init("redacted :) (its a pastebin auth lmfao)");

    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T(" "), NULL };
    ::RegisterClassEx(&wc);
    HWND hwnd = ::CreateWindow(wc.lpszClassName, NULL, WS_OVERLAPPEDWINDOW ^ WS_CAPTION ^ WS_THICKFRAME ^ WS_MAXIMIZEBOX, 100, 100, width, height, NULL, NULL, wc.hInstance, NULL);

    // 初始化Direct3D
    if (!CreateDeviceD3D(hwnd))
    {
        CleanupDeviceD3D();
        ::UnregisterClass(wc.lpszClassName, wc.hInstance);
        return 1;
    }

    // 显示窗口
    ::ShowWindow(hwnd, SW_SHOWDEFAULT);
    ::UpdateWindow(hwnd);

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO(); (void)io;

    SetupImGuiStyle();
    LoadSystemFont();

    ImGui_ImplWin32_Init(hwnd);
    ImGui_ImplDX11_Init(g_pd3dDevice, g_pd3dDeviceContext);

    MSG msg;
    ZeroMemory(&msg, sizeof(msg));
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
            continue;
        }

        ImGui_ImplDX11_NewFrame();
        ImGui_ImplWin32_NewFrame();
        ImGui::NewFrame();

        RenderMenu();
        Update();
        ImGui::Render();
        const float clear_color_with_alpha[4] = { 0.45f, 0.55f, 0.60f, 1.00f };
        g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, nullptr);
        g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
        ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

        g_pSwapChain->Present(1, 0);
    }

    ImGui_ImplDX11_Shutdown();
    ImGui_ImplWin32_Shutdown();
    ImGui::DestroyContext();

    CleanupDeviceD3D();
    DestroyWindow(hwnd);
    UnregisterClass(wc.lpszClassName, wc.hInstance);

    return 0;
}

编译命令

cl.exe 编译命令

cl /std:c++17 /EHsc /FeYourProgramName.exe main.cpp imgui.cpp imgui_draw.cpp imgui_widgets.cpp imgui_tables.cpp imgui_impl_dx11.cpp imgui_impl_win32.cpp /link d3d11.lib d3dcompiler.lib user32.lib Dwmapi.lib

g++ 编译命令

g++ main.cpp imgui.cpp imgui_draw.cpp imgui_widgets.cpp imgui_tables.cpp imgui_impl_dx11.cpp imgui_impl_win32.cpp -o your_program -lgdi32 -ld3d11 -ld3dcompiler

排查方向与解决方案

1. 修复INPUT结构体初始化问题

cl.exe与g++的结构体默认初始化规则不同,原代码中未完全初始化INPUT结构体,未赋值的字段可能携带随机内存值,导致SendInput执行异常。修改为全零初始化:

INPUT input = {0}; // 替换原代码中仅声明的INPUT input;

2. 统一结构体对齐规则

cl.exe默认对齐可能与g不一致,添加编译选项强制对齐为8字节(匹配g默认):

cl /std:c++17 /EHsc /Zp8 /FeYourProgramName.exe main.cpp imgui.cpp imgui_draw.cpp imgui_widgets.cpp imgui_tables.cpp imgui_impl_dx11.cpp imgui_impl_win32.cpp /link d3d11.lib d3dcompiler.lib user32.lib Dwmapi.lib

3. 检查按键模拟的类型安全

对MapVirtualKey的返回值强制类型转换为WORD,避免因类型不匹配导致内存溢出:

input.ki.wScan = static_cast<WORD>(MapVirtualKey(key, MAPVK_VK_TO_VSC));

4. 排查系统快捷键冲突

确认宏启用按键是否与系统显示器控制快捷键(如Win+P、Fn组合键)冲突。cl编译下可能因按键模拟的细微差异误触发系统指令,可在Update()函数中添加日志输出按键值,验证触发逻辑:

// 示例:检测F1键触发宏时输出日志
if (GetAsyncKeyState(VK_F1) & 0x8000)
{
    OutputDebugStringA("Macro activated: VK_F1\n");
    // 宏执行逻辑
}

通过DebugView工具查看输出,确认是否有意外按键被发送。

5. 禁用编译优化排查

添加/Od选项禁用cl.exe的优化,排查是否是优化导致代码逻辑异常:

cl /std:c++17 /EHsc /Zp8 /Od /FeYourProgramName.exe main.cpp imgui.cpp imgui_draw.cpp imgui_widgets.cpp imgui_tables.cpp imgui_impl_dx11.cpp imgui_impl_win32.cpp /link d3d11.lib d3dcompiler.lib user32.lib Dwmapi.lib

内容的提问来源于stack exchange,提问作者Aspis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 03:14:54