获取WM_NCHITTEST消息的坐标?

如何在C#代码中获取WM_NCHITTEST消息的坐标?
我希望获得最快的方式,因为性能是必需的。

来自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); 

直到今天早上,我已经与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); 

Casting to short为您提供正确的位置值。 我也投了x,因为你可以安排你的显示器,第二个显示器留在主显示器,因此x位置会有同样的问题。

我最近发现Point一个构造函数将为你工作。 所以,简短的版本是:

 Point pos = new Point(lParam.ToInt32()); 

我知道这个问题已经回答了,但除了…

 Point p = new Point(m.LParam.ToInt32()); 

System.Drawing.Point现在有一个专门设计用于接受这个确切值的构造函数。 严格来说,我认为这可能是最简单的方法。

说实话,我不知道当其他答案发布时,这个构造函数是否存在。

总而言之,这可能不会更快,因为takrl的答案几乎肯定是前面提到的构造函数在内部做的事情。