启动 Windows 桌面应用程序时光标繁忙的持续时间

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

当您启动 Windows 桌面应用程序时,系统会将箭头更改为带有动画繁忙微调器的箭头(大概从 IDI_ARROWIDI_APPSTARTING)。 一旦应用程序显示一个窗口,光标就会恢复以指示它已准备好输入。

对于我自己的 Win32 应用程序,即使主窗口已完全呈现并准备好进行交互,旋转器也会持续几(5?)秒。 据我了解,一旦刚刚启动的程序开始发送消息,旋转器就会消失。 更具体地说,我认为它使用与 WaitForInputIdle 相同的标准。

然而,自 Windows 10 起,某些应用程序(包括我编写的应用程序)在超时期间似乎会被繁忙的光标卡住,甚至超出应用程序响应鼠标和键盘输入的那一刻。

我应该在程序中做什么才能让系统知道初始化已完成并且不再需要旋转器?

更新:仅当从键盘启动应用程序时才会出现此问题(例如 CMD 提示符、运行窗口或使用键盘在 Visual Studio 的调试器中启动进程)。 如果您用鼠标双击该程序,微调器就会像预期的那样很快消失。

更新2:鉴于其他人无法重现,我最好的猜测是涉及到一个有缺陷的驱动程序。感谢所有在评论中帮助集思广益的人。

下面是独立的重现。

#include <Windows.h>

LRESULT OnPaint(HWND hwnd, UINT, WPARAM, LPARAM) {
    PAINTSTRUCT ps;
    ::BeginPaint(hwnd, &ps);
    RECT rc;
    ::GetClientRect(hwnd, &rc);
    ::DrawTextW(ps.hdc, L"Hello, World", -1, &rc,
                DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX);
    ::EndPaint(hwnd, &ps);
    return 0;
}

LRESULT MyWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {
        case WM_DESTROY: ::PostQuitMessage(0); break;
        case WM_PAINT:   return OnPaint(hwnd, msg, wp, lp);
    }
    return ::DefWindowProcW(hwnd, msg, wp, lp);
}

int WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int nShowCmd) {
    WNDCLASSW wc = {0};
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = MyWindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hinst;
    wc.hIcon = NULL;
    wc.hCursor = ::LoadCursorW(NULL, IDC_ARROW);
    wc.hbrBackground = ::GetSysColorBrush(COLOR_WINDOW);
    wc.lpszMenuName = nullptr;
    wc.lpszClassName = L"My Very Own Window Class";
    const ATOM atomClass = ::RegisterClassW(&wc);
    if (atomClass == 0) return ::GetLastError();

    // Ugly cast for WinAPI's legacy type punning.
    const LPCWSTR wndclass =
        reinterpret_cast<LPCWSTR>(static_cast<UINT_PTR>(atomClass));

    const HWND hwnd =
        ::CreateWindowW(wndclass, L"Test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
                        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,
                        NULL, hinst, nullptr);
    if (hwnd == NULL) return ::GetLastError();

    ::ShowWindow(hwnd, nShowCmd);

    MSG msg = {0};
    while (::GetMessageW(&msg, NULL, 0, 0) > 0) {
        ::TranslateMessage(&msg);
        ::DispatchMessageW(&msg);
    }
    return (msg.message == WM_QUIT) ? static_cast<int>(msg.wParam) : 1;
}
winapi launch mouse-cursor user32
1个回答
0
投票

我应该在程序中做什么来让系统知道初始化已完成并且不再需要旋转器?

人们似乎一致认为,一旦应用程序开始泵送消息并且没有排队的待处理输入事件,旋转器就应该消失。

事实上,这对我来说并不适用于所有情况,这可能是一个本地问题,就像一个有缺陷的驱动程序向输入队列发送垃圾邮件(不知何故永远不会进入窗口消息)。 在此处进行哈希处理没有多大意义,因此我将发布此社区 wiki 答案并继续。

© www.soinside.com 2019 - 2024. All rights reserved.