C# Winforms-单击控件的WM_NCHITEST消息
我有一个简单的windows窗体,没有边框和几个标签控件(无需单击)。我需要允许用户通过点击表单上的任意位置来移动表单,所以我找到了这个问题,并使用了下面的代码C# Winforms-单击控件的WM_NCHITEST消息,c#,.net,winforms,wndproc,C#,.net,Winforms,Wndproc,我有一个简单的windows窗体,没有边框和几个标签控件(无需单击)。我需要允许用户通过点击表单上的任意位置来移动表单,所以我找到了这个问题,并使用了下面的代码 private const int WM_NCHITTEST = 0x84; private const int HTCLIENT = 0x1; private const int HTCAPTION = 0x2; protected override void WndProc(ref Message
private const int WM_NCHITTEST = 0x84;
private const int HTCLIENT = 0x1;
private const int HTCAPTION = 0x2;
protected override void WndProc(ref Message m)
{
switch (m.Msg) {
case WM_NCHITTEST:
base.WndProc(ref m);
if ((int)m.Result == HTCLIENT) {
m.Result = (IntPtr)HTCAPTION;
return;
} else {
return;
}
break;
}
base.WndProc(ref m);
}
在某种程度上,这很有效。如果我单击表单本身的任何位置(背景),WM\u nchitest
是HTCLIENT
,因此我可以按预期移动表单。但是,如果我单击标签控件本身,消息会有所不同,我无法分辨它是什么
我找到了WM\u NCHITTEST
的各种可能值,但它们似乎都不是我所需要的
我意识到我可以禁用所有标签控件,这样我就可以像单击表单本身一样单击它们,但我想知道是否有更好/不同的方法来做到这一点
谢谢你的帮助 您正在覆盖表单的
WndProc
,但当光标位于标签上时,WM\n chittest
消息将发送到标签
您可以创建自己的标签控件,该控件派生自label
,并重写其WndProc
。这应始终返回HTTRANSPARENT
,以响应WM\u nchitest
。比如:
private const int HTTRANSPARENT = -1;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCHITTEST:
m.Result = (IntPtr)HTTRANSPARENT;
return;
}
base.WndProc(ref m);
}
还要注意,您的
WndProc
中有一个小错误。如果消息是WM\u NCHITTEST
但区域不是HTCLIENT
,则调用基类两次。您将覆盖表单的WndProc
,但当光标位于标签上时,WM\u NCHITTEST
消息将发送到标签
您可以创建自己的标签控件,该控件派生自label
,并重写其WndProc
。这应始终返回HTTRANSPARENT
,以响应WM\u nchitest
。比如:
private const int HTTRANSPARENT = -1;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCHITTEST:
m.Result = (IntPtr)HTTRANSPARENT;
return;
}
base.WndProc(ref m);
}
还要注意,您的
WndProc
中有一个小错误。如果消息是WM\u nchitest
但区域不是HTCLIENT
,那么您可以调用基类两次。为什么您不能告诉消息是什么(即它是否出错或只是返回了您不期望的内容)?记录您可以期望的值-您是否得到了其他东西?@RobP。好问题!我想我应该进入调试模式,尝试查看单击控件时的消息是什么——但不幸的是,当我将鼠标悬停在窗体上时,断点一直被击中。然后,我必须在visual studio中点击f5才能运行,并将鼠标移回窗体上,等等。我尝试在m.Result上使用debug.writeline,但无论事件实际是什么,它总是打印1而不打印其他内容。windows消息的调试可能非常棘手。Spy++是实现这类功能的必备工具。为什么你不能说出消息是什么(即它是否出错或只是返回了你不期望的东西)?记录您可以期望的值-您是否得到了其他东西?@RobP。好问题!我想我应该进入调试模式,尝试查看单击控件时的消息是什么——但不幸的是,当我将鼠标悬停在窗体上时,断点一直被击中。然后,我必须在visual studio中点击f5才能运行,并将鼠标移回窗体上,等等。我尝试在m.Result上使用debug.writeline,但无论事件实际是什么,它总是打印1而不打印其他内容。windows消息的调试可能非常棘手。Spy++是实现这类功能的必备工具。我已经修复了代码中的错误(或者至少我认为我已经修复了)。我会用自定义标签试试你的想法,然后再给你回复。如何将-1表示为十六进制?我尝试了0x-1
,但似乎不起作用…(无效数字)我也尝试了-1
,没有出现错误,但似乎与WM\u NCHITTEST
不匹配。我不想将结果设置为HTTRANSPARENT
,不过,我想将其更改为HTCLIENT
。为了澄清,测试m.Result
似乎永远不会等于HTTRANSPARENT
。不要在标签控件WndProc中测试m.Result
,只需将结果设置为HTTRANSPARENT
,如上代码所示。然后Windows将消息转发到表单,您将像以前一样返回HTCAPTION
。如果您返回标签的HTCAPTION
,Windows将忽略它。啊,我最初误解了您。刚刚测试过,效果很好-非常感谢!我已经修复了代码中的错误(或者至少我认为我已经修复了)。我会用自定义标签试试你的想法,然后再给你回复。如何将-1表示为十六进制?我尝试了0x-1
,但似乎不起作用…(无效数字)我也尝试了-1
,没有出现错误,但似乎与WM\u NCHITTEST
不匹配。我不想将结果设置为HTTRANSPARENT
,不过,我想将其更改为HTCLIENT
。为了澄清,测试m.Result
似乎永远不会等于HTTRANSPARENT
。不要在标签控件WndProc中测试m.Result
,只需将结果设置为HTTRANSPARENT
,如上代码所示。然后Windows将消息转发到表单,您将像以前一样返回HTCAPTION
。如果您返回标签的HTCAPTION
,Windows将忽略它。啊,我最初误解了您。刚刚测试过,效果很好-非常感谢!