【问题标题】:How to capture MouseUp event outside the WPF window?如何在 WPF 窗口外捕获 MouseUp 事件?
【发布时间】:2014-03-26 11:42:26
【问题描述】:

主题都在标题中。对不起,如果它是重复的,我真的在 SO 上找不到任何东西。

【问题讨论】:

标签: wpf


【解决方案1】:

嗯,非常感谢 Anatoliy Nikolaev 引导我朝着正确的方向前进! article 对我帮助很大,而 answer 对于使文章中的代码工作很有用。这就是我现在拥有的:

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;

【讨论】:

  • 我实际上并没有检查这是否有效,但只是通过它的外观 +1 。我会告诉你的,这正是我想要的。
  • 这很好用,你知道在 MouseHookProc 之后取消消息处理的方法吗,假设我有一个 winform 控件,我不想从中恢复点击事件,WM_LBUTTONDOWN 我抓住了消息进程,在某些情况下我希望它停在那里,并且控件不会接收到鼠标输入。
  • @eran otzap 如果我理解正确,如果您使用的是我回答中的代码,则需要取消订阅:MouseHook.OnMouseUp -= MouseHookMouseUp。我猜要停止接收鼠标输入的控制,您需要使用更“传统”的事件处理程序,例如control.MouseUp+=control_MouseUp,并且方法应该如下所示:void control_MouseUp(object sender, MouseButtonEventArgs e) { e.Handled = true; }
  • :) ,我正在使用 wimform 组件,它的 Z 顺序总是更高,并且会在 mouseup 路由事件处理程序之前发生。有了这些新信息,我可以再问上述问题吗?
  • WPF 中的 Winforms 组件?每次我使用 Windows Forms Host 时,都会因为空域问题而感到痛苦,有些事件根本没有收到。无论如何,你最好问一个单独的问题,如果没有一些代码,我很难意识到你需要什么:)
猜你喜欢
  • 2023-03-16
  • 2012-11-23
  • 2021-05-30
  • 2010-12-11
  • 2014-09-02
  • 2022-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多