2012-07-23 23 views
24

मेरे पास निम्न कोड है जो मुझे माउस ईवेंट कैप्चर करने के लिए कहीं से मिला है। मैंने इसे संशोधित किया और एक ईवेंट हैंडलर बनाया ताकि मैं इसकी सदस्यता ले सकूं। माउस घटनाओं को सही ढंग से कब्जा कर लिया जाता है। लेकिन यह घटना-हैंडलर को कभी नहीं निकालता है। क्या कोई इस बात को समझ सकता है कि कोड के साथ क्या गलत है?वैश्विक माउस इवेंट हैंडलर

public static class MouseHook 

{ 
    public static event EventHandler MouseAction = delegate { }; 

    public static void Start() 
    { 
     _hookID = SetHook(_proc); 


    } 
    public static void stop() 
    { 
     UnhookWindowsHookEx(_hookID); 
    } 

    private static LowLevelMouseProc _proc = HookCallback; 
    private static IntPtr _hookID = IntPtr.Zero; 

    private static IntPtr SetHook(LowLevelMouseProc proc) 
    { 
     using (Process curProcess = Process.GetCurrentProcess()) 
     using (ProcessModule curModule = curProcess.MainModule) 
     { 
      return SetWindowsHookEx(WH_MOUSE_LL, proc, 
       GetModuleHandle(curModule.ModuleName), 0); 
     } 
    } 

    private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam); 

    private static IntPtr HookCallback(
     int nCode, IntPtr wParam, IntPtr lParam) 
    { 
     if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam) 
     { 
      MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); 
      MouseAction(null,new EventArgs()); 
     } 
     return CallNextHookEx(_hookID, nCode, wParam, lParam); 
    } 

    private const int WH_MOUSE_LL = 14; 

    private enum MouseMessages 
    { 
     WM_LBUTTONDOWN = 0x0201, 
     WM_LBUTTONUP = 0x0202, 
     WM_MOUSEMOVE = 0x0200, 
     WM_MOUSEWHEEL = 0x020A, 
     WM_RBUTTONDOWN = 0x0204, 
     WM_RBUTTONUP = 0x0205 
    } 

    [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, SetLastError = true)] 
    private static extern IntPtr SetWindowsHookEx(int idHook, 
     LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId); 

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool UnhookWindowsHookEx(IntPtr hhk); 

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, 
     IntPtr wParam, IntPtr lParam); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr GetModuleHandle(string lpModuleName); 


} 

मैं इस तरह की सदस्यता लेता हूं।

MouseHook.Start(); 
    MouseHook.MouseAction += new EventHandler(Event); 

समारोह घटना प्राप्त करते हुए।

private void Event(object sender, EventArgs e) { Console.WriteLine("Left mouse click!"); } 

अद्यतन: मैं एक साथ एक open source nuget package for user action hooks.

+1

यह कंसोल मोड ऐप में काम नहीं कर सकता है, आपके प्रोग्राम को एक संदेश लूप पंप करना होगा। आवेदन। रुन() आवश्यक है। –

+0

मैं वास्तव में अपने WPF एप्लिकेशन के अंदर उपरोक्त कोड का उपयोग करता हूं। मैं App.cs 'ऑनस्टार्ट विधि से MouseHook क्लास को कॉल करता हूं। – justcoding124

+0

सभी को यह महसूस करने के लिए कि माउस खींचने का कारण बनता है, इसे एक अलग ऊंचा प्रक्रिया में चलाएं और घटनाओं को संभालने के लिए अलग-अलग धागे का उपयोग करें। – justcoding124

उत्तर

20
 return SetWindowsHookEx(WH_MOUSE_LL, proc, 
      GetModuleHandle(curModule.ModuleName), 0); 

इस कोड को असफल हो जायेगी विंडोज 8 से पहले। सीएलआर अब प्रबंधित असेंबली के लिए अप्रबंधित मॉड्यूल हैंडल अनुकरण नहीं करता है। आप अपने कोड में इस विफलता का पता नहीं लगा सकते क्योंकि इसमें आवश्यक त्रुटि जांच गुम है। GetModuleHandle और SetWindowsHookEx दोनों पर। जब आप पिनवोक करते हैं तो त्रुटि जांच को कभी भी न छोड़ें, Winapi अपवाद फेंक नहीं देता है। जांचें कि क्या वे IntPtr.Zero लौटते हैं और जब वे करते हैं तो Win32Exception को फेंक दें।

फिक्स सरल है, SetWindowsHookEx() को एक वैध मॉड्यूल हैंडल की आवश्यकता होती है लेकिन वास्तव में इसका उपयोग नहीं करते हैं जब आप निम्न-स्तरीय माउस हुक सेट करते हैं। तो कोई भी हैंडल करेगा, आप user32.dll के लिए हैंडल पास कर सकते हैं, हमेशा एक .NET अनुप्रयोग में लोड किया जाता है। ठीक करें:

IntPtr hook = SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle("user32"), 0); 
    if (hook == IntPtr.Zero) throw new System.ComponentModel.Win32Exception(); 
    return hook; 
+0

धन्यवाद। लेकिन मैंने कोड को ठीक से संशोधित किया। जब मैं कंसोल का उपयोग करता हूं तो समन्वय दिखाने के लिए प्रयोग किया जाता था। राइटलाइन (hookStruct.pt.x + "," + hookStruct.pt .y) HookCallback समारोह के अंदर। अब अपने काम नहीं कर रहा। – justcoding124

+0

एर्म, इंतजार, इस के साथ "यह काम नहीं कर रहा" शुरू कर दिया। यह वास्तव में काम कर रहा था? सकते हैं आप नेट और Windows का उपयोग कर रहे कम से कम दस्तावेज़ संस्करण? आप क्या आउटपुट विंडो में प्रथम मौका अपवाद देखें? –

+0

हाँ, यह माउस समन्वय दे रहा था जब मैं कल काम कर रहा था। असल में मैं अगर घटना पर नज़र रखने डिबग पथ का उपयोग कर निकाल दिया जाता है की जाँच की। हाँ यह करता है! लेकिन Console.WriteLine (" कुछ ") कोई आउटपुट नहीं दिखाता है। मुझे लगता है कि कंसोल। राइटलाइन सही ढंग से काम नहीं कर रहा है। अजीब – justcoding124

8

के रूप में आप वर्णित यह होना चाहिए मैं बस एक साधारण खिड़कियों के रूप में अपने कोड और उसके काम करने की नकल की करने के लिए काम कर रहे कोड डाल दिया। आप इसका उपयोग कैसे कर रहे हैं? आप कहां से शुरू कर रहे हैं और घटना को जोड़ रहे हैं?

और पूर्णता के लिए इस कोड को मैं के साथ समाप्त हो गया है - एक सरल सी # प्रपत्र टेम्पलेट से शुरू कर दिया है जब आप एक Windows संस्करण पर .NET 4 पर चला

using System; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 

namespace WindowsFormsApplication1 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 

      MouseHook.Start(); 
      MouseHook.MouseAction += new EventHandler(Event); 
     } 

     private void Event(object sender, EventArgs e) { Console.WriteLine("Left mouse click!"); } 
    } 

    public static class MouseHook 
    { 
     public static event EventHandler MouseAction = delegate { }; 

     public static void Start() 
     { 
      _hookID = SetHook(_proc); 


     } 
     public static void stop() 
     { 
      UnhookWindowsHookEx(_hookID); 
     } 

     private static LowLevelMouseProc _proc = HookCallback; 
     private static IntPtr _hookID = IntPtr.Zero; 

     private static IntPtr SetHook(LowLevelMouseProc proc) 
     { 
      using (Process curProcess = Process.GetCurrentProcess()) 
      using (ProcessModule curModule = curProcess.MainModule) 
      { 
       return SetWindowsHookEx(WH_MOUSE_LL, proc, 
        GetModuleHandle(curModule.ModuleName), 0); 
      } 
     } 

     private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam); 

     private static IntPtr HookCallback(
      int nCode, IntPtr wParam, IntPtr lParam) 
     { 
      if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam) 
      { 
       MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); 
       MouseAction(null, new EventArgs()); 
      } 
      return CallNextHookEx(_hookID, nCode, wParam, lParam); 
     } 

     private const int WH_MOUSE_LL = 14; 

     private enum MouseMessages 
     { 
      WM_LBUTTONDOWN = 0x0201, 
      WM_LBUTTONUP = 0x0202, 
      WM_MOUSEMOVE = 0x0200, 
      WM_MOUSEWHEEL = 0x020A, 
      WM_RBUTTONDOWN = 0x0204, 
      WM_RBUTTONUP = 0x0205 
     } 

     [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, SetLastError = true)] 
     private static extern IntPtr SetWindowsHookEx(int idHook, 
      LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId); 

     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool UnhookWindowsHookEx(IntPtr hhk); 

     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, 
      IntPtr wParam, IntPtr lParam); 

     [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     private static extern IntPtr GetModuleHandle(string lpModuleName); 


    } 
} 
+0

अगर मैं माउसक्लिक के निर्देशांक जानना चाहता हूं, तो मुझे क्या करना चाहिए? –

+0

5 वें बटन को छोड़कर सभी माउस बटन ईवेंट के लिए काम करता है। असल में चौथा और 5 वां बटन एक ही कोड लौटाता है। – Masum

+0

मैंने अभी यह किया है। सार्वजनिक स्थैतिक int x = 0; // Program.cs और MyConsoleApp.Program.x = hookStruct.pt.x में चला जाता है; // हुककॉलबैक –

संबंधित मुद्दे