winapi - Forkert hotspot til I-Beam markør i Windows 7?

Indlæg af Hanne Mølgaard Plasc

Problem



Problemet


På vinduer er koordinaterne, der returneres til en 'museknap ned' -hændelse, tilsyneladende lidt forkert for en I-Beam-markør. Dybest set er x-koordinaten altid to pixler tilbage af hvor den skal være.


Jeg har skrevet et meget simpelt win32-program til at demonstrere problemet. Alt det gør er at vende markøren til en IBeam og gøre en lodret rød linje, hvor den sidste mus ned begivenhed var. Jeg ville forvente, at den røde linje matchede præcis med lodret del af I-strålen, men det er ikke tilfældet.


Her er et skærmbillede af hvad der sker . [7]


Som du kan se, er den røde linje to pixel til venstre for hvor den skal være (adfærd er korrekt for standardpilot), så det ser ud til at hotspot til I-Beam-markøren er forkert.


Jeg har haft en anden, der kører Windows 7 64 bit, bekræfter at de oplever det samme problem, men en anden tester på Vista har ikke problemet.





Nogle oplysninger om mit miljø



  • Windows 7 64 bit. Helt standard konfiguration (dvs. ingen DPI skalering, ingen underlige temaer osv.)

  • Visual Studio Express 2010

  • NVidia grafikkort med nyeste drivere (v270.61)

  • At skifte aero til eller fra, gør ingen forskel. At vælge forskellige markører i visningsindstillinger gør ingen forskel






De relevante kodeord


Mit testprojekt er i grunden 'Win32 Project' -skabelonen i Visual C ++ 2010 med de ændringer, der skitseres nedenfor.


Her er koden, hvor jeg registrerer vinduesklassen og sæt markøren til en I Beam


ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS\_HREDRAW | CS\_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI\_CURSOR\_TEST));
    wcex.hCursor        = LoadCursor(NULL, IDC\_IBEAM); // this is the only line I changed in this function
    wcex.hbrBackground  = (HBRUSH)(COLOR\_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCE(IDC\_CURSOR\_TEST);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI\_SMALL));

    return RegisterClassEx(&wcex);
}


Her er de relevante dele fra min hovedbeskedsløjfe:


case WM\_LBUTTONDOWN:
    // record position of mouse down. 
    // xPos and yPos are just declared as
    // global ints for the purpose of this test
    xPos = GET\_X\_LPARAM(lParam); 
    yPos = GET\_Y\_LPARAM(lParam);
    // cause redraw
    InvalidateRect(hWnd, NULL, TRUE);
    UpdateWindow(hWnd);
    break;      

case WM\_PAINT:
    // paint vertical red line at position of last click
    hdc = BeginPaint(hWnd, &ps);
    RECT rcClient;
    GetClientRect(hWnd, &rcClient);
    hPen = CreatePen(PS\_SOLID, 1, RGB(255, 0, 0));
    SelectObject(hdc, hPen);
    MoveToEx(hdc, xPos, 0, NULL);
    LineTo(hdc, xPos, rcClient.bottom);
    DeleteObject(hPen);
    EndPaint(hWnd, &ps);
    break;


Sammendrag


Jeg har lavet masser af googling til svar, men kan ikke finde noget relevant. Gør jeg noget galt med, hvordan jeg håndterer de indkommende markørkoordinater?


Tak!





EDIT: Mere information efter indsigtige spørgsmål i kommentarerne


Som ledet af @ Mark Ransom i kommentarerne, har jeg brugt funktionen GetIconInfo for at få mere information om I-Beam markøren. ICONINFO struct for markøren angiver, at x-koordinatoren for markøren hotspot er ved x=8. Men når jeg dumper bitmapet til markøren (hbmMask medlemmet af ICONINFO struct, som det er en monokrom markør), er den lodrette bjælke 10 pixels fra venstre for billedet, ikke 8 pixels. Som Mark påpeger, er dette sandsynligvis årsagen til den visuelle diskrepency, men hvorfor har det fundet sted, og hvordan kan jeg rette det?


(Jeg har også bemærket, at svaret på dette andet spørgsmål har nogle interessante oplysninger om den forskellige måde, som I-Beam cursors håndteres. Jeg spekulerer på, om dette er relevant)

Bedste reference