C++:WinAPI.当标准光标在程序屏幕的工作表面之外时,将其转换为您自己的光标

C++: WinAPI. Convert the standard cursor to your own when it is outside the working surface of the program screen

本文关键字:光标 转换 自己的 工作 标准 WinAPI 程序 C++ 屏幕 表面      更新时间:2024-05-10

当标准光标在程序屏幕的工作面之外时,我需要将其转换为自己的光标。最初,当我离开窗口时,光标在屏幕上是标准的——我自己的,应该是这样。我把它放回——又是标准的。但当我再次走出窗户时,它不再变成我的了。也就是说,它只起作用一次。错误在哪里?

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
TRACKMOUSEEVENT tme;
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static BOOL bMouseInside;
switch (message) 
{
case WM_CREATE:
{
RECT rt;
POINT pt = { 0, 0 };

GetClientRect(hWnd, &rt);
ClientToScreen(hWnd, &pt);
OffsetRect(&rt, pt.x, pt.y);

GetCursorPos(&pt);
bMouseInside = PtInRect(&rt, pt);

tme.cbSize = sizeof(tme);
tme.dwFlags = TME_HOVER;
tme.hwndTrack = hWnd;
tme.dwHoverTime = HOVER_DEFAULT;
_TrackMouseEvent(&tme);
}
break;

case WM_COMMAND:
wmId    = LOWORD(wParam); 
wmEvent = HIWORD(wParam); 
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;

case WM_MOUSEMOVE: {
tme.cbSize = sizeof(tme);
tme.hwndTrack = hWnd;
tme.dwFlags = TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;

_TrackMouseEvent(&tme);

if (!bMouseInside)
{
SetSystemCursor(def_arrow_cur, 32512);
DestroyCursor(def_arrow_cur);
bMouseInside = TRUE;
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
}
break;

case WM_MOUSELEAVE:
tme.cbSize = sizeof(tme);
tme.hwndTrack = hWnd;
tme.dwFlags = TME_HOVER;
tme.dwHoverTime = HOVER_DEFAULT;

_TrackMouseEvent(&tme);

if (bMouseInside)
{
SetSystemCursor(my_cur, 32512);
DestroyCursor(my_cur);
bMouseInside = FALSE;
InvalidateRect(hWnd, NULL, TRUE);
UpdateWindow(hWnd);
}
break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hWnd, message, wParam, lParam);
}

return 0;
}

原生游标和标准游标是这样创建的:

HCURSOR def_arrow_cur = CopyCursor(LoadCursor(0, IDC_ARROW));
HCURSOR my_cur = LoadCursorFromFile(TEXT("my.cur"));

来自文档:

备注

DestroyCursor函数会破坏非共享游标。请勿使用此函数销毁共享游标。共享游标的有效性为只要从中加载它的模块保留在存储器中。这个以下函数获得共享光标:

  • LoadCursor
  • LoadCursorFromFile
  • LoadImage(如果使用LR_SHARED标志(
  • CopyImage(如果使用LR_COPYRETURNORG标志并且hImage参数是共享光标(

但你仍然这么做。