2014-03-26 64 views
3

題目全部在標題中。對不起,如果它是重複的,我真的找不到任何東西。如何在WPF窗口外捕獲MouseUp事件?

+1

看到這個['link'](http://www.codeproject.com/Questions/362352/Csharp -Mouse-Event-outside-the-Form),它指的是'WinForms',但對於WPF將是相同的。也看到這個問題:http://stackoverflow.com/questions/13732070/how-can-i-capture-mouse-events-that-occur-outside-of-a-wpf-window –

回答

3

嗯,非常感謝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; 
+0

我實際上沒有檢查如果這工作,但只是由它的外觀+1。 我會告訴你,這正是我一直在尋找的。 –

+0

這個工程很好,你知道一個方法來取消到MouseHookProc後的消息處理,可以說我有一個winform控件 ,我不想恢復從它的單擊事件,WM_LBUTTONDOWN我趕上消息處理,並在某些條件我希望它停在那裏,並且控件不會收到鼠標輸入。 –

+0

@eran otzap如果我理解正確,如果您使用我的答案中的代碼,則需要退訂:'MouseHook.OnMouseUp - = MouseHookMouseUp'。爲了停止控制接收鼠標輸入,我想,你需要使用一個更加「傳統的」事件處理程序,比如'control.MouseUp + = control_MouseUp'和一個方法應該是這樣的:'void control_MouseUp(object sender,MouseButtonEventArgs e) { e.Handled = true; }' – lena

相關問題