对于键盘方面,您可以尝试在
UserControl
中覆盖
ProcessCmdKey
事件。
UserControl.cs
:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
return base.ProcessCmdKey(ref msg, keyData);
}
对于鼠标,我想象您的UserControl实现
IMessageFilter接口的
PreFilterMessage方法可能是前进的方向(尽管我不确定是否可以特定于用户控件)。
编辑
我快速查看了一下
IMessageFilter
,我认为我有一个可能有效的解决方案,尽管它似乎有点复杂。
创建一个实现
IMessageFilter
的
MessageHandler
。
class MessageHandler : IMessageFilter
{
private int WM_LBUTTONUP = 0x0202;
private int WM_MBUTTONUP = 0x0208;
private int WM_RBUTTONUP = 0x0205;
List<IntPtr> windowHandles = new List<IntPtr>();
public MessageHandler(List<IntPtr> wnds)
{
windowHandles = wnds;
}
public bool PreFilterMessage(ref Message m)
{
if (windowHandles.Contains(m.HWnd) && (m.Msg == WM_LBUTTONUP || m.Msg == WM_MBUTTONUP || m.Msg == WM_RBUTTONUP))
{
Debug.WriteLine("Clicked");
}
return false;
}
}
在您的用户控件(或新类)中,您可以使用P/Invoke来获取给定父级的子窗口。 来自
pinvoke.net。
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
private static List<IntPtr> GetChildWindows(IntPtr parent, bool addParent = true)
{
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
if (addParent)
result.Add(parent);
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
// You can modify this to check to see if you want to cancel the operation, then return a null here
return true;
}
"GetChildWindows"函数将会返回我们所需要的窗口。我稍作修改,添加了一个可选的布尔型参数"addParent",它将会把用户控件自身添加到列表中。
在你的"UserControl.cs"构造函数中,我们可以注册"MessageFilter"并传递句柄列表(或者只要你知道用户控件的句柄,你也可以通过其他方式添加)。
public MyControl()
{
InitializeComponent();
Application.AddMessageFilter(new MessageHandler(GetChildWindows(this.Handle)));
}
现在,您应该能够检测到用户控件及其子窗口中的三个鼠标按钮松开事件。不要忘记在应用程序关闭或您的UserControl关闭/释放时调用Application.RemoveMessageFilter。就像我说的那样,这并不是最简单的方法,但如果标准事件处理程序无法正常工作(我假设您已经尝试订阅标准鼠标单击事件),它将捕获点击。