启动Windows桌面应用程序时游标处于繁忙状态的持续时间



当您启动Windows桌面应用程序时,系统将箭头更改为带有动画忙碌转轴的箭头(假设从IDI_ARROW更改为IDI_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;
}

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

大家似乎一致认为,一旦应用程序开始抽取消息并且没有挂起的输入事件队列,旋转器就应该消失。

对我来说,并非在所有情况下都工作的事实可能是一个本地问题,就像一个有bug的驱动程序向输入队列发送垃圾邮件(不知何故从未使其成为窗口消息)。在SO上讨论这个问题没有多大意义,所以我把这个社区wiki的答案放在上面,然后继续前进。

最新更新