如何捕获WPF窗口外的MouseUp事件?
题目全在标题里。抱歉,如果是复制品,我真的找不到任何东西。好吧,非常感谢Anatoliy Nikolaev为我指引了正确的方向!这对我帮助很大,这对于使文章中的代码正常工作非常有用。这就是我现在拥有的:如何捕获WPF窗口外的MouseUp事件?,wpf,Wpf,题目全在标题里。抱歉,如果是复制品,我真的找不到任何东西。好吧,非常感谢Anatoliy Nikolaev为我指引了正确的方向!这对我帮助很大,这对于使文章中的代码正常工作非常有用。这就是我现在拥有的: internal static class MouseHook { private delegate int HookProc(int nCode, int wParam, IntPtr lParam); private static int _mouseHookHandle;
internal static class MouseHook
{
private delegate int HookProc(int nCode, int wParam, IntPtr lParam);
private static int _mouseHookHandle;
private static HookProc _mouseDelegate;
private static event MouseUpEventHandler MouseUp;
public static event MouseUpEventHandler OnMouseUp
{
add
{
Subscribe();
MouseUp += value;
}
remove
{
MouseUp -= value;
Unsubscribe();
}
}
private static void Unsubscribe()
{
if (_mouseHookHandle != 0)
{
int result = UnhookWindowsHookEx(_mouseHookHandle);
_mouseHookHandle = 0;
_mouseDelegate = null;
if (result == 0)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode);
}
}
}
private static void Subscribe()
{
if (_mouseHookHandle == 0)
{
_mouseDelegate = MouseHookProc;
_mouseHookHandle = SetWindowsHookEx(WH_MOUSE_LL,
_mouseDelegate,
GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName),
0);
if (_mouseHookHandle == 0)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode);
}
}
}
private static int MouseHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
MSLLHOOKSTRUCT mouseHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
if (wParam == WM_LBUTTONUP)
{
if (MouseUp != null)
{
MouseUp.Invoke(null, new Point(mouseHookStruct.pt.x, mouseHookStruct.pt.y));
}
}
}
return CallNextHookEx(_mouseHookHandle, nCode, wParam, lParam);
}
private const int WH_MOUSE_LL = 14;
private const int WM_LBUTTONUP = 0x0202;
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
private static extern int UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name);
}
public delegate void MouseUpEventHandler(object sender, Point p);
使用它非常简单:
MouseHook.OnMouseUp += MouseHookMouseUp;
见此,它指的是
WinForms
,但对于WPF则是相同的。还可以看到这个问题:我实际上没有检查它是否有效,只是看它+1。我会让你知道,这正是我想要的。这很好用,你知道一种方法可以在鼠标点击后取消消息处理,比如说我有一个winform控件,我不想从它还原点击事件,WM_LBUTTONDOWN我捕获消息进程,在某种情况下我希望它停止在那里,控件将不会收到鼠标输入。@eran otzap如果我理解正确,如果您使用的是我回答中的代码,则需要取消订阅:MouseHook.OnMouseUp-=MouseHookMouseUp
。要停止控件接收鼠标输入,我想,您需要使用一个更“传统”的事件处理程序,比如control.MouseUp+=control\u MouseUp
,方法应该是这样的:void control\u MouseUp(object sender,MouseButtonEventArgs e){e.Handled=true;}
,我使用的是一个wimform组件,它的Z顺序总是更高,并且会出现在mouseup路由事件处理程序之前。有了这些新信息,我可以重新问上面的问题吗?WPF中的Winforms组件?每次我使用Windows窗体主机时,都会因为空域问题而感到痛苦,有些事件根本没有收到。无论如何,你最好问一个单独的问题,如果没有一些代码,我很难理解你需要什么:)