繪製鼠標光標 (Draw mouse 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.


參考解法

方法 1:

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.

方法 2:

For what it's worth:

Another approach that might be worth looking at is to use a WS_EX_TOPMOST|WS_EX_LAYERED window that you move around as needed, and let Windows handle the drawing/transparency for you. This has the advantage that it won't interfere at all with the drawing main window, and will work even if the main window has child controls or similar.

It will also allow your 'mouse pointer' to 'hang over the edge' of your window - eg. when when mouse is positioned to point at the extreme bottom-right pixel, the tail and arrow of a regular mouse pointer will be over the frame and other windows behind it, and you can't do this just by drawing your own window's client area.

--

Having said that, I'm not sure that 'faking' the mouse position is the proper thing to do here, though it may well get you up and running. Another approach is to let the mouse behave as normal, but for apps that require the higher resolution, have another API that exposes the more exact values. Along with the usual mouse/keyboard messages and APIs, windows also has various techniques and APIs  (eg Raw Input) for getting input information, defining additional input devices, and I think also associating additional information with messages, and one of those techniques might be more appropriate here. It might be worthwhile to re-ask your question, but focus on the higher-level on, not the cursor drawing.

(by daveskinkBrendanMcK)

參考文件

  1. Draw mouse cursor (CC BY-SA 3.0/4.0)

#gdi #winapi #mouse-cursor






相關問題

繪製鼠標光標 (Draw mouse cursor)

C 和 Windows GDI 中的雙緩衝 *framework* (Double-buffering *framework* in C and Windows GDI)

一個進程的 GDI 洩漏會影響其他進程嗎? (Can GDI leaks from one process affect other processes?)

BeginPath Textout EndPath 繪製反轉文本 (BeginPath Textout EndPath draws inverted text)

監控GDI通話 (Monitoring GDI calls)

如何捕獲(並希望修復)GDI 資源洩漏 (How to catch (and hopefully fix) a GDI resource leak)

如何使用 GDI(+) 在內存中渲染漸變 (How to render a gradient in memory using GDI(+))

使用 BITMAP::bmBits 與 GetDIBits 有什麼區別? (What is the difference between using BITMAP::bmBits vs GetDIBits?)

獲取背景窗口的縮略圖 (Get Thumbnail of background window)

AlphaBlend 返回“假”的原因可能是什麼 (What could be the reason for AlphaBlend to return 'false')

在 C++ 中查找像素 RGB 數據的最快方法是什麼? (What is the fastest method to lookup pixel RGB data in C++?)

逐行讀取文本框並將其視為單獨的文本 (Read a textbox line by line and treat it as a separate text)







留言討論