title: Incorrect hotspot for I-Beam cursor in Windows 7?
body: <p><strong>The Problem</strong></p>
  
  <p>On windows, the coordinates returned for a "mouse button down" event seem to be slightly wrong for an I-Beam cursor. Basically, the x-coordinate is always two pixels left of where it should be.</p>
  
  <p>I've written a very simple win32 program to demonstrate the problem. All it does is turn the cursor into an IBeam and render a vertical red line where the last mouse down event was. I would expect the red line to match up exactly with the vertical part of the I-Beam, but this is not the case.</p>
  
  <p><a href="http://postimage.org/image/1o6dytux0/" rel="nofollow noreferrer"><strong>Here's a screenshot of what happens</strong></a>. </p>
  
  <p>As you can see, the red line is two pixels to the left of where it should be (the behaviour is correct for the standard arrow pointer), so it appears that the hotspot for the I-Beam cursor is wrong.</p>
  
  <p>I've had someone else running Windows 7 64 bit confirm that they experience the same problem, but another tester on Vista does not have the problem.</p>
  
  <hr>
  
  <p><strong>Some information about my environment</strong></p>
  
  <ul>
  <li>Windows 7 64 bit. Completely default configuration (i.e. no DPI scaling, no weird themes etc)</li>
  <li>Visual Studio Express 2010</li>
  <li>NVidia graphics card with latest drivers (v270.61)</li>
  <li>Switching aero on or off makes no difference. Choosing different cursors in display preferences makes no difference</li>
  </ul>
  
  <hr>
  
  <p><strong>The Relevant Bits Of Code</strong></p>
  
  <p>My test project is basically the "Win32 Project" template in Visual C++ 2010, with the changes outlined below.</p>
  
  <p>Here's the code where I register the window class and set the cursor to an I Beam </p>
  
  <pre><code>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(&amp;wcex);
  }
  </code></pre>
  
  <p>Here are the relevant parts from my main message loop:</p>
  
  <pre><code>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, &amp;ps);
      RECT rcClient;
      GetClientRect(hWnd, &amp;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, &amp;ps);
      break;
  </code></pre>
  
  <p><strong>The Summary</strong></p>
  
  <p>I've done loads of googling for answers, but can't find anything relevant. Am I doing something wrong with the way that I'm handling the incoming cursor coordinates?</p>
  
  <p>Thanks!</p>
  
  <hr>
  
  <p><strong>EDIT: More Information After Insightful Questions in the Comments</strong></p>
  
  <p>As guided by @Mark Ransom in the comments, I've used the <code>GetIconInfo</code> function to get more information about the I-Beam cursor. The <code>ICONINFO</code> struct for the cursor indicates that the x coord for the cursor hotspot is at x=8. However, when I dump the bitmap for the cursor (the <code>hbmMask</code> member of the <code>ICONINFO</code> struct, as it is a monochrome cursor), the vertical bar is 10 pixels from the left of the image, not 8 pixels. As Mark points out this is likely the cause of the visual discrepency, but why has this occurred, and how might I fix it? </p>
  
  <p>(I also noticed that the answer to <a href="https://stackoverflow.com/questions/918990/c-capturing-the-mouse-cursor-image"><strong>this other question</strong></a> has some interesting information about the different way that I-Beam cursors are handled. I wonder if this is relevant)</p>