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

  api, c++, mouseevent, winapi

I need to convert the standard cursor to my own when it is outside the working surface of the program screen. Initially, the cursor is standard on the screen, when I leave the window – my own, as it should be. I return it back – again the standard one. But when I go out the window again, it no longer changes to mine. That is, it works only once. Where is the mistake?

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;
}

The native and standard cursors are created like this:

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

Source: Windows Questions C++

LEAVE A COMMENT