【发布时间】:2011-08-14 21:24:27
【问题描述】:
问题
在 Windows 上,对于 I-Beam 光标,“鼠标按下”事件返回的坐标似乎有些错误。基本上,x 坐标总是在它应该在的位置左边两个像素。
我编写了一个非常简单的 win32 程序来演示这个问题。它所做的只是将光标变为 IBeam 并在最后一次鼠标按下事件所在的位置呈现一条垂直红线。我希望红线与工字梁的垂直部分完全匹配,但事实并非如此。
Here's a screenshot of what happens。
如您所见,红线在它应该在的位置左侧两个像素处(对于标准箭头指针的行为是正确的),因此看来 I-Beam 光标的热点是错误的。
我已经让其他运行 Windows 7 64 位的人确认他们遇到了同样的问题,但在 Vista 上的另一位测试人员没有遇到问题。
关于我的环境的一些信息
- Windows 7 64 位。完全默认配置(即没有 DPI 缩放、没有奇怪的主题等)
- Visual Studio Express 2010
- 带有最新驱动程序 (v270.61) 的 NVidia 显卡
- 打开或关闭气动没有区别。在显示首选项中选择不同的光标没有区别
相关代码
我的测试项目基本上是 Visual C++ 2010 中的“Win32 项目”模板,变化如下所述。
这是我注册窗口类并将光标设置为 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);
}
以下是我的主消息循环中的相关部分:
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;
总结
我已经在谷歌上搜索了很多答案,但找不到任何相关信息。我处理传入光标坐标的方式有问题吗?
谢谢!
编辑:在评论中提出有见地的问题后的更多信息
在 cmets 中 @Mark Ransom 的指导下,我使用了 GetIconInfo 函数来获取有关 I-Beam 光标的更多信息。游标的ICONINFO 结构表明游标热点的x 坐标位于x=8。但是,当我转储光标的位图(ICONINFO 结构的hbmMask 成员,因为它是单色光标)时,垂直条距图像左侧 10 像素,而不是 8 像素。正如马克指出的那样,这可能是视觉差异的原因,但为什么会发生这种情况,我该如何解决?
(我还注意到this other question 的答案有一些关于 I-Beam 光标的不同处理方式的有趣信息。我想知道这是否相关)
【问题讨论】:
-
您可以使用
GetIconInfo获取热点坐标,这样可以解决问题。 -
嗨@Mark-Ransom。
GetIconInfo告诉我 IDC_IBEAM 指针的热点是xHotspot==8 yHotspot==9。 (作为参考,该函数告诉我标准 IDC_ARROW 指针的热点是xHotspot==0 yHotspot==0)。我可以从这些信息中获得更多信息吗?谢谢。 -
点击点应该在相对于光标图像左上角的热点坐标上。如果您可以转储光标位图并对其进行检查,则垂直条也应距左侧 8 个像素。如果不是,那就是你的问题。
-
好的,我已经转储了光标位图(好吧,实际上我已经从
ICONINFO结构中转储了hbmMask位图GetIconInfo。hbmColor位图不是' t 设置,因为 I-Beam 是单色光标)。结果是垂直条距左侧 10 个像素,而不是 xHotspot 成员指示的 8 个像素。正如@Mark 指出的那样,这显然是错误的,但我完全不知道结构中如何存在这种相互冲突的信息以及如何修复它。 -
我知道为什么会这样,但这更像是一种解决方法。当然,我要么 (a) 做错了什么,要么 (b) 内置 I-Beam 光标的热点对于 Windows 7 的所有用户都不准确?换句话说,我更愿意在采取变通办法之前尝试找出问题的根本原因。我希望这看起来是合理的;)
标签: windows user-interface winapi windows-7 mouse-cursor