我的WinForm C#应用程序上的MouseEvents存在问题。
我希望所有鼠标点击我的应用程序,但我不想在每个子组件中都放置一个监听器,也不想使用Windows鼠标挂钩。
在Flash上我可以在舞台上放置一个监听器来获取电影上的所有MouseEvent。
C#上有这样的东西吗?全局MouseListener?
修改
我从IMessageFilter和使用Application.AddMessageFilter创建了这个类。
public class GlobalMouseHandler : IMessageFilter{
private const int WM_LBUTTONDOWN = 0x201;
public bool PreFilterMessage(ref Message m){
if (m.Msg == WM_LBUTTONDOWN) {
// Do stuffs
}
return false;
}
}
并将此代码放在需要监听全局点击的控件上:
GlobalMouseHandler globalClick = new GlobalMouseHandler();
Application.AddMessageFilter(globalClick);
答案 0 :(得分:15)
执行此操作的一种简单方法是通过调用Application.AddMessageFilter
并编写实现IMessageFilter
接口的类来添加消息循环过滤器。
通过IMessageFilter.PreFilterMessage
,您的类可以看到通过应用程序的消息循环传递的任何输入消息。 PreFilterMessage
还可以决定是否将这些消息传递给他们所指定的特定控件。
此方法引入的一个复杂性是必须通过传递给PreFilterMessage
方法的Message结构来处理Windows消息。这意味着在WM\_LBUTTONDOWN, WM\_MOUSEMOVE
,WM\_LBUTTONUP
等上引用Win32文档,而不是传统的MouseDown
,MouseMove
和MouseUp
事件。
答案 1 :(得分:5)
样本类
class CaptureEvents : IMessageFilter
{
#region IMessageFilter Members
public delegate void Callback(int message);
public event Callback MessageReceived;
IntPtr ownerWindow;
Hashtable interestedMessages = null;
CaptureEvents(IntPtr handle, int[] messages)
{
ownerWindow = handle;
for(int c = 0; c < messages.Length ; c++)
{
interestedMessages[messages[c]] = 0;
}
}
public bool PreFilterMessage(ref Message m)
{
if (m.HWnd == ownerWindow && interestedMessages.ContainsKey(m.Msg))
{
MessageReceived(m.Msg);
}
return true;
}
#endregion
}
答案 2 :(得分:3)
Take a look at this article。它递归地挂起所有控制事件并广播它们。您也可以在表单中覆盖WndProc。
答案 3 :(得分:3)
如果您不想通过重写Form.PreProcessMessage或Form.WndProc来处理消息,那么您可以继承Form以将事件处理程序挂钩到表单上各种控件的所有MouseClick事件。
编辑:忘记通过窗体上控件的子控件来递归。
public class MousePreviewForm : Form
{
protected override void OnClosed(EventArgs e)
{
UnhookControl(this as Control);
base.OnClosed(e);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
HookControl(this as Control);
}
private void HookControl(Control controlToHook)
{
controlToHook.MouseClick += AllControlsMouseClick;
foreach (Control ctl in controlToHook.Controls)
{
HookControl(ctl);
}
}
private void UnhookControl(Control controlToUnhook)
{
controlToUnhook.MouseClick -= AllControlsMouseClick;
foreach (Control ctl in controlToUnhook.Controls)
{
UnhookControl(ctl);
}
}
void AllControlsMouseClick(object sender, MouseEventArgs e)
{
//do clever stuff here...
throw new NotImplementedException();
}
}
您的表单需要从MousePreviewForm派生而不是System.Windows.Forms.Form。