【发布时间】:2015-10-25 14:20:12
【问题描述】:
我需要在应用程序启动后立即隐藏鼠标光标。我为此使用 ShowCursor(FALSE)。但通常在 ShowCursor(FALSE) 之后,光标会一直停留在屏幕上,直到鼠标移动。我和其他人在 Windows 从 XP 到 10 的不同 PC 上重现了这个。为了重现这个,只需通过双击可执行文件从 Windows 资源管理器启动应用程序,然后绝对不要在双击和之后移动鼠标。如果应用程序以任何其他方式启动,则光标会按预期隐藏。似乎光标停留在屏幕上时属于Windows资源管理器,有时除了屏幕上的光标之外仍然是资源管理器工具提示。
并非总是有效的代码:
#include <Windows.h>
LRESULT __stdcall WndProcFull(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg==WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pszCmdLine, int iCmdShow)
{
MSG msg;
HWND hWnd;
PCWSTR pszFullName=L"FullWindow";
WNDCLASSEX wc={sizeof (WNDCLASSEX), 0, WndProcFull, 0, 0, hInstance, 0, LoadCursor(0, IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), 0, pszFullName, 0};
RegisterClassEx(&wc);
hWnd=CreateWindow(pszFullName, L"HideCursor", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE, 0, 0, 0, 0, 0, 0, hInstance, 0);
UpdateWindow(hWnd);
ShowCursor(FALSE);
while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
return 0;
}
源代码在任何VS中编译。
目前唯一有用的是设置计时器,并且在计时器间隔到期后,以编程方式移动鼠标光标,然后隐藏。但我更愿意找到更合适、更稳定的解决方案。
带有解决方法的代码:
#include <Windows.h>
#define HIDECURSOR_TIMER_ID 1
LRESULT __stdcall WndProcFull(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_TIMER:
POINT pt;
GetCursorPos(&pt);
SetCursorPos(pt.x+1, pt.y);
KillTimer(hWnd, HIDECURSOR_TIMER_ID);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pszCmdLine, int iCmdShow)
{
MSG msg;
HWND hWnd;
PCWSTR pszFullName=L"FullWindow";
WNDCLASSEX wc={sizeof (WNDCLASSEX), 0, WndProcFull, 0, 0, hInstance, 0, LoadCursor(0, IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), 0, pszFullName, 0};
RegisterClassEx(&wc);
hWnd=CreateWindow(pszFullName, L"HideCursor", WS_POPUP | WS_MAXIMIZE | WS_VISIBLE, 0, 0, 0, 0, 0, 0, hInstance, 0);
UpdateWindow(hWnd);
ShowCursor(FALSE);
SetTimer(hWnd, HIDECURSOR_TIMER_ID, 200, 0);
while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
return 0;
}
200 毫秒是光标稳定消失的最小超时值。
【问题讨论】:
-
当我在没有计时器黑客的情况下尝试它时工作得很好。做有效的事。
-
可能您在双击可执行文件时稍微移动了鼠标?当另外两个人停止移动鼠标时,他们也能够在其他计算机上重现这一点。
-
显而易见的问题:为什么要注册一个具有非空光标的窗口类?你为什么不处理WM_SETCURSOR?
-
因为在原来的应用程序中我经常需要在这个窗口中再次显示光标。用空游标的情况也是一样的,我已经试过了。
-
第二个问题呢?如果您想操作光标,处理
WM_SETCURSOR似乎很自然。