आप SetWindowsHookEx का उपयोग कर सकते हैं ताकि निम्न स्तर के हुक को पकड़ने (विशिष्ट) विंडोज संदेशों को सेट किया जा सके। विशेष रूप से इन हुक-आईडी निगरानी के लिए दिलचस्प हो सकता है:
WH_CALLWNDPROC
(4) एक हुक प्रक्रिया है कि संदेशों पर नज़र रखता है इससे पहले कि प्रणाली उन्हें गंतव्य विंडो प्रक्रिया के लिए भेजता है स्थापित करता है। अधिक जानकारी के लिए, CallWndProc हुक प्रक्रिया देखें।
WH_CALLWNDPROCRET
(12) एक हुक प्रक्रिया है कि संदेशों की निगरानी करता है के बाद वे गंतव्य विंडो प्रक्रिया द्वारा संसाधित किया गया है स्थापित करता है। अधिक जानकारी के लिए, CallWndRetProc हुक प्रक्रिया देखें।
यह कुछ समय हो गया है क्योंकि मैंने इसे लागू किया है, लेकिन एक उदाहरण के रूप में मैंने बेस क्लास पोस्ट किया है जिसका उपयोग मैं विशिष्ट संदेशों को हुक करने के लिए करता हूं। (उदाहरण के लिए, मैंने इसे वैश्विक मूसहेल ट्रैपर में उपयोग किया है, जो सुनिश्चित करता है कि मेरे Winforms ऐप्स इंटरनेट एक्सप्लोरर के समान व्यवहार करते हैं: सक्रिय नियंत्रण की बजाय कर्सर के नीचे नियंत्रण स्क्रॉल करें)।
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Subro.Win32;
namespace Subro
{
/// <summary>
/// Base class to relatively safely register global windows hooks
/// </summary>
public abstract class GlobalHookTrapper : FinalizerBase
{
[DllImport("user32", EntryPoint = "SetWindowsHookExA")]
static extern IntPtr SetWindowsHookEx(int idHook, Delegate lpfn, IntPtr hmod, IntPtr dwThreadId);
[DllImport("user32", EntryPoint = "UnhookWindowsHookEx")]
private static extern int UnhookWindowsHookEx(IntPtr hHook);
[DllImport("user32", EntryPoint = "CallNextHookEx")]
static extern int CallNextHook(IntPtr hHook, int ncode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentThreadId();
IntPtr hook;
public readonly int HookId;
public readonly GlobalHookTypes HookType;
public GlobalHookTrapper(GlobalHookTypes Type):this(Type,false)
{
}
public GlobalHookTrapper(GlobalHookTypes Type, bool OnThread)
{
this.HookType = Type;
this.HookId = (int)Type;
del = ProcessMessage;
if (OnThread)
hook = SetWindowsHookEx(HookId, del, IntPtr.Zero, GetCurrentThreadId());
else
{
var hmod = IntPtr.Zero; // Marshal.GetHINSTANCE(GetType().Module);
hook = SetWindowsHookEx(HookId, del, hmod, IntPtr.Zero);
}
if (hook == IntPtr.Zero)
{
int err = Marshal.GetLastWin32Error();
if (err != 0)
OnHookFailed(err);
}
}
protected virtual void OnHookFailed(int Error)
{
throw Win32Functions.TranslateError(Error);
}
private const int HC_ACTION = 0;
[MarshalAs(UnmanagedType.FunctionPtr)]
private MessageDelegate del;
private delegate int MessageDelegate(int code, IntPtr wparam, IntPtr lparam);
private int ProcessMessage(int hookcode, IntPtr wparam, IntPtr lparam)
{
if (HC_ACTION == hookcode)
{
try
{
if (Handle(wparam, lparam)) return 1;
}
catch { }
}
return CallNextHook(hook, hookcode, wparam, lparam);
}
protected abstract bool Handle(IntPtr wparam, IntPtr lparam);
protected override sealed void OnDispose()
{
UnhookWindowsHookEx(hook);
AfterDispose();
}
protected virtual void AfterDispose()
{
}
}
public enum GlobalHookTypes
{
BeforeWindow = 4, //WH_CALLWNDPROC
AfterWindow = 12, //WH_CALLWNDPROCRET
KeyBoard = 2, //WH_KEYBOARD
KeyBoard_Global = 13, //WH_KEYBOARD_LL
Mouse = 7, //WH_MOUSE
Mouse_Global = 14, //WH_MOUSE_LL
JournalRecord = 0, //WH_JOURNALRECORD
JournalPlayback = 1, //WH_JOURNALPLAYBACK
ForeGroundIdle = 11, //WH_FOREGROUNDIDLE
SystemMessages = 6, //WH_SYSMSGFILTER
MessageQueue = 3, //WH_GETMESSAGE
ComputerBasedTraining = 5, //WH_CBT
Hardware = 8, //WH_HARDWARE
Debug = 9, //WH_DEBUG
Shell = 10, //WH_SHELL
}
public abstract class FinalizerBase : IDisposable
{
protected readonly AppDomain domain;
public FinalizerBase()
{
System.Windows.Forms.Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
domain = AppDomain.CurrentDomain;
domain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
domain.DomainUnload += new EventHandler(domain_DomainUnload);
}
private bool disposed;
public bool IsDisposed{get{return disposed;}}
public void Dispose()
{
if (!disposed)
{
GC.SuppressFinalize(this);
if (domain != null)
{
domain.ProcessExit -= new EventHandler(CurrentDomain_ProcessExit);
domain.DomainUnload -= new EventHandler(domain_DomainUnload);
System.Windows.Forms.Application.ApplicationExit -= new EventHandler(Application_ApplicationExit);
}
disposed = true;
OnDispose();
}
}
void Application_ApplicationExit(object sender, EventArgs e)
{
Dispose();
}
void domain_DomainUnload(object sender, EventArgs e)
{
Dispose();
}
void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
Dispose();
}
protected abstract void OnDispose();
/// Destructor
~FinalizerBase()
{
Dispose();
}
}
}
सी # ऐसा नहीं कर सकता। सी ++ कर सकते हैं। – Alex
@alex - सी # ऐसा क्यों करने में सक्षम नहीं होगा? –
@ डैनियलए। व्हाइट प्लेटफार्म संदेश कतार केवल देशी कोड में ही संभाला जा सकता है, जहां तक मैं समझता हूं, इसलिए ऐसा नहीं लगता है कि सी # ऐसा कर सकता है (इसे प्रबंधित किया जा रहा है और सभी) ... मैं खुश से अधिक होगा अगर मैं गलत था तो अगर आप मुझे अलग-अलग समझने के लिए स्वतंत्र महसूस करते हैं (मैं कुछ समय के लिए खुद का कोई फायदा नहीं उठा रहा हूं) – Alex