如何在C#代码中获取WM_NCHITTEST消息的坐标?
我希望得到最快的方式,因为性能是必需的。
答案 0 :(得分:13)
直到今天早上,我已经与Thomas Levesques的回答100%同意了,我从msdn中提取了相同的信息,而且代码(貌似)工作得很好。但是,有一种情况会让你感到困惑,我今天下午花了三个小时才找到原因。
我的症状是,在我的一台开发机器上,在VS2010 IDE中,我的控件只能通过点击我在某个y位置点击它来选择。窗体顶部的非常小的控件无法通过单击进行选择。不可点击的区域大小看起来与Windows窗体设计器周围的IDE大小相同,所以起初我以为我有一些奇怪的鲜为人知的DesignMode问题。最令人困惑的是,完全相同的项目(在不同的机器上检出TFS)不会显示此行为。
以下是发生的事情:
考虑一下你有一个双显示器设置,如图所示(抱歉德国截图,我手头没有英文操作系统):
如您所见,监视器2的左上角位于坐标(1280,-256)处。如果您使用上面显示的解决方案,如果鼠标确实在-30,您将获得65505之类的y。这是因为这些位置存储为LParam的高阶和低阶WORD
。因此,执行(lParam.ToInt32() & 0xFFFF0000) >> 16
将为y位置提供正确的位。但是,将此转换为int会产生65505,因为您正在转换为错误的数据类型。
解决方案:
int x = (short)(lParam.ToInt32() & 0x0000FFFF);
int y = (short)((lParam.ToInt32() & 0xFFFF0000) >> 16);
Point pos = new Point(x, y);
投射到short
会为您提供正确的位置值。我也投了x,因为你可以安排你的显示器,使第二个显示器留在主显示器上,因此x位置会有同样的问题。
我最近发现Point
的一个构造函数将为你工作。所以,简短版本是:
Point pos = new Point(lParam.ToInt32());
答案 1 :(得分:11)
来自MSDN:
<强>的wParam 强>
不使用此参数。<强> lParam的强>
低位字指定 光标的x坐标。该 坐标是相对于 屏幕的左上角。
高阶词指定了 光标的y坐标。该 坐标是相对于 屏幕的左上角。
所以你只需要从消息lParam
中提取低阶和高阶词:
int x = lParam.ToInt32() & 0x0000FFFF;
int y = (int)((lParam.ToInt32() & 0xFFFF0000) >> 16)
Point pos = new Point(x, y);
我不会太担心性能,因为这些操作只是位级算术......
请注意,这些坐标是相对于屏幕的。如果您想要相对于控件(或表单)的坐标,可以使用PointToClient
方法:
Point relativePos = theControl.PointToClient(pos);
答案 2 :(得分:8)
我知道这个问题已经回答了,但除了......
Point p = new Point(m.LParam.ToInt32());
System.Drawing.Point现在有一个专门设计用于接受这个确切值的构造函数。严格地说,我认为这可能是最简单的方式。
说实话,我不知道在发布其他答案时这个构造函数是否存在。
所有人都说,这可能不是更快,因为takrl的答案几乎肯定是前面提到的构造函数在内部的作用。