C# 禁用 click/doubleClick 或任何 WindowsMessage
C# Disable click/doubleClick or any WindowsMessage
我的目标是禁用我的应用程序中的所有 DoubleClick()
事件。只是简单地取消订阅这些事件是不可能的,因为那些是外部自定义控件。所以我的目标是为这些控件或我的整个应用程序禁用 DoubleClick()
,这并不重要。
我想做的是一旦 window 收到 WindowsMessage WM
并且 ID 号 Message.Msg
是例如Button.Click()
事件。
private const int WM_COMMAND = // ???
if (m.Msg == WM_COMMAND)
...
但是无论我使用哪种 WindowsMessage 通知代码,我都无法得到正确的通知代码,一旦单击控件就会触发该通知代码。但我很高兴在 Form
上对 DoubeClick()
进行干预。
private const int WM_NCLBUTTONDBLCLK = 0x00A3;
private const int WM_LBUTTONDBLCLK = 0x0203;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_NCLBUTTONDBLCLK || m.Msg == WM_LBUTTONDBLCLK)
{
m.Result = IntPtr.Zero;
return;
}
base.WndProc(ref m);
}
这完全没问题,并且在客户区和[=21]的非客户区上取消了DoubleClick
=].但是当我悬停在控件上时,我定位在哪个区域?因为那些 WindowsMessages 指的是 客户区 和 非客户区 当我在控件上时不要被触发。
Sent when the user clicks a button.
The parent window of the button receives this notification code through the WM_COMMAND message.
MSDN doc about a button click notifaction message
WM_COMMAND
消息具有此通知代码:
private const int WM_COMMAND = 0x0111;
因此,当我尝试对发送的这条消息做出反应时,我做不到,因为这条消息没有被触发。
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_COMMAND)
MessageBox.Show("foo"); // nothing happens
base.WndProc(ref m);
}
我对这个 WindowsMessage 遗漏了什么或误解了什么?
因为还没有人发布答案,我在这里找到了一个很好的解决方案,我尝试禁用所有 DoubleClick()
s 或仅 one/a 几个想要的 Control
/s。
问题是 WndProc()
不过滤或响应正在发送的 所有 WM
。因此,无法检测到 非客户区 0x0203
上默认 doubleClick
的 WM
。所以我更深入地在 WM
到达 WndProc()
之前过滤它们。一种方法是使用分配给我的 Application
.
的 MessageFilter
private MessageFilter msgFilter = new MessageFilter();
Application.AddMessageFilter(msgFilter);
方法Param是我自己的一个对象classMessageFilter
,需要实现IMessageFilter
接口才能使用PreFilterMessage()
。为发送到您的应用程序的 each 个 WM
调用此方法。
class MessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == 0x0203)
{
m.Result = IntPtr.Zero;
return true;
}
else
return false;
}
}
所以基本上一旦有一个 WM
具有所需的 Message.Msg
ID,我将 Result
设置为 zero
所以 DoubleClick()
被完全禁用对于整个应用程序。
后来发现最好只从一个 Control
禁用 DoubleClick()
。由于 Windows 中的每个 Control
都有一个唯一的 Handle HWnd
,它是 Message
的一部分,如果某个 Message
瞄准了我,我可以用它来扫描具体单曲Control
.
当您创建 Control
时,可以在 .Designer.cs
中订阅事件:
this.yourControl.HandleCreated += new System.EventHandler(this.yourControl_HandleCreated);
或者,如果它是自定义 Control
,请在事件创建后订阅它。如果您将创建的 Handle
的值分配给您的 MessageFilter
可以访问的任何实例,例如此 class.
中的 Property
private void yourControl_HandleCreated(object sender, EventArgs e)
{
msgFilter.OwnHandle = yourControl.Handle;
}
之后只需在 if
语句中添加第二个条件:
if (m.Msg == 0x0203 && OwnHandle == m.HWnd)
...
我的目标是禁用我的应用程序中的所有 DoubleClick()
事件。只是简单地取消订阅这些事件是不可能的,因为那些是外部自定义控件。所以我的目标是为这些控件或我的整个应用程序禁用 DoubleClick()
,这并不重要。
我想做的是一旦 window 收到 WindowsMessage WM
并且 ID 号 Message.Msg
是例如Button.Click()
事件。
private const int WM_COMMAND = // ???
if (m.Msg == WM_COMMAND)
...
但是无论我使用哪种 WindowsMessage 通知代码,我都无法得到正确的通知代码,一旦单击控件就会触发该通知代码。但我很高兴在 Form
上对 DoubeClick()
进行干预。
private const int WM_NCLBUTTONDBLCLK = 0x00A3;
private const int WM_LBUTTONDBLCLK = 0x0203;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_NCLBUTTONDBLCLK || m.Msg == WM_LBUTTONDBLCLK)
{
m.Result = IntPtr.Zero;
return;
}
base.WndProc(ref m);
}
这完全没问题,并且在客户区和[=21]的非客户区上取消了DoubleClick
=].但是当我悬停在控件上时,我定位在哪个区域?因为那些 WindowsMessages 指的是 客户区 和 非客户区 当我在控件上时不要被触发。
Sent when the user clicks a button. The parent window of the button receives this notification code through the WM_COMMAND message.
MSDN doc about a button click notifaction message
WM_COMMAND
消息具有此通知代码:
private const int WM_COMMAND = 0x0111;
因此,当我尝试对发送的这条消息做出反应时,我做不到,因为这条消息没有被触发。
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_COMMAND)
MessageBox.Show("foo"); // nothing happens
base.WndProc(ref m);
}
我对这个 WindowsMessage 遗漏了什么或误解了什么?
因为还没有人发布答案,我在这里找到了一个很好的解决方案,我尝试禁用所有 DoubleClick()
s 或仅 one/a 几个想要的 Control
/s。
问题是 WndProc()
不过滤或响应正在发送的 所有 WM
。因此,无法检测到 非客户区 0x0203
上默认 doubleClick
的 WM
。所以我更深入地在 WM
到达 WndProc()
之前过滤它们。一种方法是使用分配给我的 Application
.
MessageFilter
private MessageFilter msgFilter = new MessageFilter();
Application.AddMessageFilter(msgFilter);
方法Param是我自己的一个对象classMessageFilter
,需要实现IMessageFilter
接口才能使用PreFilterMessage()
。为发送到您的应用程序的 each 个 WM
调用此方法。
class MessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == 0x0203)
{
m.Result = IntPtr.Zero;
return true;
}
else
return false;
}
}
所以基本上一旦有一个 WM
具有所需的 Message.Msg
ID,我将 Result
设置为 zero
所以 DoubleClick()
被完全禁用对于整个应用程序。
后来发现最好只从一个 Control
禁用 DoubleClick()
。由于 Windows 中的每个 Control
都有一个唯一的 Handle HWnd
,它是 Message
的一部分,如果某个 Message
瞄准了我,我可以用它来扫描具体单曲Control
.
当您创建 Control
时,可以在 .Designer.cs
中订阅事件:
this.yourControl.HandleCreated += new System.EventHandler(this.yourControl_HandleCreated);
或者,如果它是自定义 Control
,请在事件创建后订阅它。如果您将创建的 Handle
的值分配给您的 MessageFilter
可以访问的任何实例,例如此 class.
Property
private void yourControl_HandleCreated(object sender, EventArgs e)
{
msgFilter.OwnHandle = yourControl.Handle;
}
之后只需在 if
语句中添加第二个条件:
if (m.Msg == 0x0203 && OwnHandle == m.HWnd)
...