Search code examples
winapigdimouse-cursor

Draw mouse cursor


I'm trying to simulate a mouse cursor in Win32 forms. On every WM_MOUSEMOVE I have

hCursor = LoadCursor(NULL, IDC_ARROW);
////Get device context
hDeviceContext = GetDC(hwnd);
hDCMem = CreateCompatibleDC(hDeviceContext);
hBitmap = CreateCompatibleBitmap(hDCMem, 50, 50);
hbmOld = SelectObject(hDCMem, hBitmap);
DrawIcon(hDCMem, x, y, hCursor);
SelectObject(hDCMem, hbmOld);

But I don't see anything being drawn. However if I drew directly on the DC:

DrawIcon(hDeviceContext, x, y, hCursor);

I do see the cursor but it does not erase the image as I move the cursor, leaving a long tail behind.


Solution

  • Don't paint in WM_MOUSEMOVE, that's what WM_PAINT is for. Basically, you need to handle three messages:

        case WM_CREATE:
            hCursor = LoadCursor(NULL, IDC_ARROW);
            cWidth  = GetSystemMetrics(SM_CXCURSOR); // saving the cursor dimensions
            cHeight = GetSystemMetrics(SM_CYCURSOR);
        break;
    
        case WM_MOUSEMOVE:
            rcOld = rcNew;
            rcNew.left   = GET_X_LPARAM(lParam);     // saving the mouse coordinates
            rcNew.top    = GET_Y_LPARAM(lParam);
            rcNew.right  = rcNew.left + cWidth;
            rcNew.bottom = rcNew.top + cHeight;
            InvalidateRect(hwnd, &rcOld, TRUE);      // asking to redraw the rectangles
            InvalidateRect(hwnd, &rcNew, TRUE);
            UpdateWindow(hwnd);
        break;
    
        case WM_PAINT:
            hDC = BeginPaint(hwnd, &ps);
            DrawIcon(hDC, rcNew.left, rcNew.top, hCursor);
            EndPaint(hwnd, &ps);
        break;
    

    Note: I'm not sure what do you mean by "simulating a mouse cursor", but there could be a better way of doing what you probably want. Please check functions SetCursor() and SetWindowLongPtr() with GCL_HCURSOR.