Click here to Skip to main content
15,897,273 members
Articles / Programming Languages / C#

Using Window Messages to Implement Global System Hooks in C#

Rate me:
Please Sign up or sign in to vote.
4.88/5 (68 votes)
3 May 2007GPL311 min read 376.1K   14.9K   255  
Explains how to implement any type of global system hook in C# by using an unmanaged C++ DLL and Windows messages.
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace GlobalHooksTest
{
	public class GlobalHooks
	{
		public delegate void HookReplacedEventHandler();
		public delegate void WindowEventHandler(IntPtr Handle);
		public delegate void SysCommandEventHandler(int SysCommand, int lParam);
		public delegate void ActivateShellWindowEventHandler();
		public delegate void TaskmanEventHandler();
		public delegate void BasicHookEventHandler(IntPtr Handle1, IntPtr Handle2);
		public delegate void WndProcEventHandler(IntPtr Handle, IntPtr Message, IntPtr wParam, IntPtr lParam);

		// Functions imported from our unmanaged DLL
		[DllImport("GlobalCbtHook.dll")]
		private static extern bool InitializeCbtHook(int threadID, IntPtr DestWindow);
		[DllImport("GlobalCbtHook.dll")]
		private static extern void UninitializeCbtHook();
		[DllImport("GlobalCbtHook.dll")]
		private static extern bool InitializeShellHook(int threadID, IntPtr DestWindow);
		[DllImport("GlobalCbtHook.dll")]
		private static extern void UninitializeShellHook();
		[DllImport("GlobalCbtHook.dll")]
		private static extern void InitializeKeyboardHook(int threadID, IntPtr DestWindow);
		[DllImport("GlobalCbtHook.dll")]
		private static extern void UninitializeKeyboardHook();
		[DllImport("GlobalCbtHook.dll")]
		private static extern void InitializeMouseHook(int threadID, IntPtr DestWindow);
		[DllImport("GlobalCbtHook.dll")]
		private static extern void UninitializeMouseHook();
		[DllImport("GlobalCbtHook.dll")]
		private static extern void InitializeKeyboardLLHook(int threadID, IntPtr DestWindow);
		[DllImport("GlobalCbtHook.dll")]
		private static extern void UninitializeKeyboardLLHook();
		[DllImport("GlobalCbtHook.dll")]
		private static extern void InitializeMouseLLHook(int threadID, IntPtr DestWindow);
		[DllImport("GlobalCbtHook.dll")]
		private static extern void UninitializeMouseLLHook();
		[DllImport("GlobalCbtHook.dll")]
		private static extern void InitializeCallWndProcHook(int threadID, IntPtr DestWindow);
		[DllImport("GlobalCbtHook.dll")]
		private static extern void UninitializeCallWndProcHook();
		[DllImport("GlobalCbtHook.dll")]
		private static extern void InitializeGetMsgHook(int threadID, IntPtr DestWindow);
		[DllImport("GlobalCbtHook.dll")]
		private static extern void UninitializeGetMsgHook();

		// API call needed to retreive the value of the messages to intercept from the unmanaged DLL
		[DllImport("user32.dll")]
		private static extern int RegisterWindowMessage(string lpString);
		[DllImport("user32.dll")]
		private static extern IntPtr GetProp(IntPtr hWnd, string lpString);
		[DllImport("user32.dll")]
		private static extern IntPtr GetDesktopWindow();

		// Handle of the window intercepting messages
		private IntPtr _Handle;

		private CBTHook _CBT;
		private ShellHook _Shell;
		private KeyboardHook _Keyboard;
		private MouseHook _Mouse;
		private KeyboardLLHook _KeyboardLL;
		private MouseLLHook _MouseLL;
		private CallWndProcHook _CallWndProc;
		private GetMsgHook _GetMsg;

		public GlobalHooks(IntPtr Handle)
		{
			_Handle = Handle;

			_CBT = new CBTHook(_Handle);
			_Shell = new ShellHook(_Handle);
			_Keyboard = new KeyboardHook(_Handle);
			_Mouse = new MouseHook(_Handle);
			_KeyboardLL = new KeyboardLLHook(_Handle);
			_MouseLL = new MouseLLHook(_Handle);
			_CallWndProc = new CallWndProcHook(_Handle);
			_GetMsg = new GetMsgHook(_Handle);
		}

		~GlobalHooks()
		{
			_CBT.Stop();
			_Shell.Stop();
			_Keyboard.Stop();
			_Mouse.Stop();
			_KeyboardLL.Stop();
			_MouseLL.Stop();
			_CallWndProc.Stop();
			_GetMsg.Stop();
		}

		public void ProcessWindowMessage(ref System.Windows.Forms.Message m)
		{
			_CBT.ProcessWindowMessage(ref m);
			_Shell.ProcessWindowMessage(ref m);
			_Keyboard.ProcessWindowMessage(ref m);
			_Mouse.ProcessWindowMessage(ref m);
			_KeyboardLL.ProcessWindowMessage(ref m);
			_MouseLL.ProcessWindowMessage(ref m);
			_CallWndProc.ProcessWindowMessage(ref m);
			_GetMsg.ProcessWindowMessage(ref m);
		}

		#region Accessors

		public CBTHook CBT
		{
			get { return _CBT; }
		}

		public ShellHook Shell
		{
			get { return _Shell; }
		}

		public KeyboardHook Keyboard
		{
			get { return _Keyboard; }
		}

		public MouseHook Mouse
		{
			get { return _Mouse; }
		}

		public KeyboardLLHook KeyboardLL
		{
			get { return _KeyboardLL; }
		}

		public MouseLLHook MouseLL
		{
			get  { return _MouseLL; }
		}

		public CallWndProcHook CallWndProc
		{
			get { return _CallWndProc; }
		}

		public GetMsgHook GetMsg
		{
			get { return _GetMsg; }
		}

		#endregion

		public abstract class Hook
		{
			protected bool _IsActive = false;
			protected IntPtr _Handle;

			public Hook(IntPtr Handle)
			{
				_Handle = Handle;
			}

			public void Start()
			{
				if (!_IsActive)
				{
					_IsActive = true;
					OnStart();
				}
			}

			public void Stop()
			{
				if (_IsActive)
				{
					OnStop();
					_IsActive = false;
				}
			}

			~Hook()
			{
				Stop();
			}

			public bool IsActive
			{
				get { return _IsActive; }
			}

			protected abstract void OnStart();
			protected abstract void OnStop();
			public abstract void ProcessWindowMessage(ref System.Windows.Forms.Message m);
		}

		public class CBTHook : Hook
		{
			// Values retreived with RegisterWindowMessage
			private int _MsgID_CBT_HookReplaced;
			private int _MsgID_CBT_Activate;
			private int _MsgID_CBT_CreateWnd;
			private int _MsgID_CBT_DestroyWnd;
			private int _MsgID_CBT_MinMax;
			private int _MsgID_CBT_MoveSize;
			private int _MsgID_CBT_SetFocus;
			private int _MsgID_CBT_SysCommand;

			public event HookReplacedEventHandler HookReplaced;
			public event WindowEventHandler Activate;
			public event WindowEventHandler CreateWindow;
			public event WindowEventHandler DestroyWindow;
			public event WindowEventHandler MinMax;
			public event WindowEventHandler MoveSize;
			public event WindowEventHandler SetFocus;
			public event SysCommandEventHandler SysCommand;

			public CBTHook(IntPtr Handle) : base(Handle)
			{
			}

			protected override void OnStart()
			{
				// Retreive the message IDs that we'll look for in WndProc
				_MsgID_CBT_HookReplaced = RegisterWindowMessage("WILSON_HOOK_CBT_REPLACED");
				_MsgID_CBT_Activate = RegisterWindowMessage("WILSON_HOOK_HCBT_ACTIVATE");
				_MsgID_CBT_CreateWnd = RegisterWindowMessage("WILSON_HOOK_HCBT_CREATEWND");
				_MsgID_CBT_DestroyWnd = RegisterWindowMessage("WILSON_HOOK_HCBT_DESTROYWND");
				_MsgID_CBT_MinMax = RegisterWindowMessage("WILSON_HOOK_HCBT_MINMAX");
				_MsgID_CBT_MoveSize = RegisterWindowMessage("WILSON_HOOK_HCBT_MOVESIZE");
				_MsgID_CBT_SetFocus = RegisterWindowMessage("WILSON_HOOK_HCBT_SETFOCUS");
				_MsgID_CBT_SysCommand = RegisterWindowMessage("WILSON_HOOK_HCBT_SYSCOMMAND");

				// Start the hook
				InitializeCbtHook(0, _Handle);
			}

			protected override void OnStop()
			{
				UninitializeCbtHook();
			}

			public override void ProcessWindowMessage(ref System.Windows.Forms.Message m)
			{
				if (m.Msg == _MsgID_CBT_HookReplaced)
				{
					if (HookReplaced != null)
						HookReplaced();
				}
				else if (m.Msg == _MsgID_CBT_Activate)
				{
					if (Activate != null)
						Activate(m.WParam);
				}
				else if (m.Msg == _MsgID_CBT_CreateWnd)
				{
					if (CreateWindow != null)
						CreateWindow(m.WParam);
				}
				else if (m.Msg == _MsgID_CBT_DestroyWnd)
				{
					if (DestroyWindow != null)
						DestroyWindow(m.WParam);
				}
				else if (m.Msg == _MsgID_CBT_MinMax)
				{
					if (MinMax != null)
						MinMax(m.WParam);
				}
				else if (m.Msg == _MsgID_CBT_MoveSize)
				{
					if (MoveSize != null)
						MoveSize(m.WParam);
				}
				else if (m.Msg == _MsgID_CBT_SetFocus)
				{
					if (SetFocus != null)
						SetFocus(m.WParam);
				}
				else if (m.Msg == _MsgID_CBT_SysCommand)
				{
					if (SysCommand != null)
						SysCommand(m.WParam.ToInt32(), m.LParam.ToInt32());
				}
			}
		}

		public class ShellHook : Hook
		{
			// Values retreived with RegisterWindowMessage
			private int _MsgID_Shell_ActivateShellWindow;
			private int _MsgID_Shell_GetMinRect;
			private int _MsgID_Shell_Language;
			private int _MsgID_Shell_Redraw;
			private int _MsgID_Shell_Taskman;
			private int _MsgID_Shell_HookReplaced;
			private int _MsgID_Shell_WindowActivated;
			private int _MsgID_Shell_WindowCreated;
			private int _MsgID_Shell_WindowDestroyed;

			public event HookReplacedEventHandler HookReplaced;
			public event ActivateShellWindowEventHandler ActivateShellWindow;
			public event WindowEventHandler GetMinRect;
			public event WindowEventHandler Language;
			public event WindowEventHandler Redraw;
			public event TaskmanEventHandler Taskman;
			public event WindowEventHandler WindowActivated;
			public event WindowEventHandler WindowCreated;
			public event WindowEventHandler WindowDestroyed;

			public ShellHook(IntPtr Handle) : base(Handle)
			{
			}

			protected override void OnStart()
			{
				// Retreive the message IDs that we'll look for in WndProc
				_MsgID_Shell_HookReplaced = RegisterWindowMessage("WILSON_HOOK_SHELL_REPLACED");
				_MsgID_Shell_ActivateShellWindow = RegisterWindowMessage("WILSON_HOOK_HSHELL_ACTIVATESHELLWINDOW");
				_MsgID_Shell_GetMinRect = RegisterWindowMessage("WILSON_HOOK_HSHELL_GETMINRECT");
				_MsgID_Shell_Language = RegisterWindowMessage("WILSON_HOOK_HSHELL_LANGUAGE");
				_MsgID_Shell_Redraw = RegisterWindowMessage("WILSON_HOOK_HSHELL_REDRAW");
				_MsgID_Shell_Taskman = RegisterWindowMessage("WILSON_HOOK_HSHELL_TASKMAN");
				_MsgID_Shell_WindowActivated = RegisterWindowMessage("WILSON_HOOK_HSHELL_WINDOWACTIVATED");
				_MsgID_Shell_WindowCreated = RegisterWindowMessage("WILSON_HOOK_HSHELL_WINDOWCREATED");
				_MsgID_Shell_WindowDestroyed = RegisterWindowMessage("WILSON_HOOK_HSHELL_WINDOWDESTROYED");

				// Start the hook
				InitializeShellHook(0, _Handle);
			}

			protected override void OnStop()
			{
				UninitializeShellHook();
			}

			public override void ProcessWindowMessage(ref System.Windows.Forms.Message m)
			{
				if (m.Msg == _MsgID_Shell_HookReplaced)
				{
					if (HookReplaced != null)
						HookReplaced();
				}
				else if (m.Msg == _MsgID_Shell_ActivateShellWindow)
				{
					if (ActivateShellWindow != null)
						ActivateShellWindow();
				}
				else if (m.Msg == _MsgID_Shell_GetMinRect)
				{
					if (GetMinRect != null)
						GetMinRect(m.WParam);
				}
				else if (m.Msg == _MsgID_Shell_Language)
				{
					if (Language != null)
						Language(m.WParam);
				}
				else if (m.Msg == _MsgID_Shell_Redraw)
				{
					if (Redraw != null)
						Redraw(m.WParam);
				}
				else if (m.Msg == _MsgID_Shell_Taskman)
				{
					if (Taskman != null)
						Taskman();
				}
				else if (m.Msg == _MsgID_Shell_WindowActivated)
				{
					if (WindowActivated != null)
						WindowActivated(m.WParam);
				}
				else if (m.Msg == _MsgID_Shell_WindowCreated)
				{
					if (WindowCreated != null)
						WindowCreated(m.WParam);
				}
				else if (m.Msg == _MsgID_Shell_WindowDestroyed)
				{
					if (WindowDestroyed != null)
						WindowDestroyed(m.WParam);
				}
			}
		}

		public class KeyboardHook : Hook
		{
			// Values retreived with RegisterWindowMessage
			private int _MsgID_Keyboard;
			private int _MsgID_Keyboard_HookReplaced;

			public event HookReplacedEventHandler HookReplaced;
			public event BasicHookEventHandler KeyboardEvent;

			public KeyboardHook(IntPtr Handle) : base(Handle)
			{
			}

			protected override void OnStart()
			{
				// Retreive the message IDs that we'll look for in WndProc
				_MsgID_Keyboard = RegisterWindowMessage("WILSON_HOOK_KEYBOARD");
				_MsgID_Keyboard_HookReplaced = RegisterWindowMessage("WILSON_HOOK_KEYBOARD_REPLACED");

				// Start the hook
				InitializeKeyboardHook(0, _Handle);
			}
			protected override void OnStop()
			{
				UninitializeKeyboardHook();
			}

			public override void ProcessWindowMessage(ref System.Windows.Forms.Message m)
			{
				if (m.Msg == _MsgID_Keyboard)
				{
					if (KeyboardEvent != null)
						KeyboardEvent(m.WParam, m.LParam);
				}
				else if (m.Msg == _MsgID_Keyboard_HookReplaced)
				{
					if (HookReplaced != null)
						HookReplaced();
				}
			}
		}

		public class MouseHook : Hook
		{
			// Values retreived with RegisterWindowMessage
			private int _MsgID_Mouse;
			private int _MsgID_Mouse_HookReplaced;

			public event HookReplacedEventHandler HookReplaced;
			public event BasicHookEventHandler MouseEvent;

			public MouseHook(IntPtr Handle) : base(Handle)
			{
			}

			protected override void OnStart()
			{
				// Retreive the message IDs that we'll look for in WndProc
				_MsgID_Mouse = RegisterWindowMessage("WILSON_HOOK_MOUSE");
				_MsgID_Mouse_HookReplaced = RegisterWindowMessage("WILSON_HOOK_MOUSE_REPLACED");

				// Start the hook
				InitializeMouseHook(0, _Handle);
			}
			protected override void OnStop()
			{
				UninitializeMouseHook();
			}

			public override void ProcessWindowMessage(ref System.Windows.Forms.Message m)
			{
				if (m.Msg == _MsgID_Mouse)
				{
					if (MouseEvent != null)
						MouseEvent(m.WParam, m.LParam);
				}
				else if (m.Msg == _MsgID_Mouse_HookReplaced)
				{
					if (HookReplaced != null)
						HookReplaced();
				}
			}
		}

		public class KeyboardLLHook : Hook
		{
			// Values retreived with RegisterWindowMessage
			private int _MsgID_KeyboardLL;
			private int _MsgID_KeyboardLL_HookReplaced;

			public event HookReplacedEventHandler HookReplaced;
			public event BasicHookEventHandler KeyboardLLEvent;

			public KeyboardLLHook(IntPtr Handle) : base(Handle)
			{
			}

			protected override void OnStart()
			{
				// Retreive the message IDs that we'll look for in WndProc
				_MsgID_KeyboardLL = RegisterWindowMessage("WILSON_HOOK_KEYBOARDLL");
				_MsgID_KeyboardLL_HookReplaced = RegisterWindowMessage("WILSON_HOOK_KEYBOARDLL_REPLACED");

				// Start the hook
				InitializeKeyboardLLHook(0, _Handle);
			}

			protected override void OnStop()
			{
				UninitializeKeyboardLLHook();
			}

			public override void ProcessWindowMessage(ref System.Windows.Forms.Message m)
			{
				if (m.Msg == _MsgID_KeyboardLL)
				{
					if (KeyboardLLEvent != null)
						KeyboardLLEvent(m.WParam, m.LParam);
				}
				else if (m.Msg == _MsgID_KeyboardLL_HookReplaced)
				{
					if (HookReplaced != null)
						HookReplaced();
				}
			}
		}

		public class MouseLLHook : Hook
		{
			// Values retreived with RegisterWindowMessage
			private int _MsgID_MouseLL;
			private int _MsgID_MouseLL_HookReplaced;

			public event HookReplacedEventHandler HookReplaced;
			public event BasicHookEventHandler MouseLLEvent;
			public event MouseEventHandler MouseDown;
			public event MouseEventHandler MouseMove;
			public event MouseEventHandler MouseUp;

			private const int WM_MOUSEMOVE                    = 0x0200;
			private const int WM_LBUTTONDOWN                  = 0x0201;
			private const int WM_LBUTTONUP                    = 0x0202;
			private const int WM_LBUTTONDBLCLK                = 0x0203;
			private const int WM_RBUTTONDOWN                  = 0x0204;
			private const int WM_RBUTTONUP                    = 0x0205;
			private const int WM_RBUTTONDBLCLK                = 0x0206;
			private const int WM_MBUTTONDOWN                  = 0x0207;
			private const int WM_MBUTTONUP                    = 0x0208;
			private const int WM_MBUTTONDBLCLK                = 0x0209;
			private const int WM_MOUSEWHEEL                   = 0x020A;

			struct MSLLHOOKSTRUCT 
			{
				public System.Drawing.Point pt;
				public int mouseData;
				public int flags;
				public int time;
				public IntPtr dwExtraInfo;
			};

			public MouseLLHook(IntPtr Handle) : base(Handle)
			{
			}

			protected override void OnStart()
			{
				// Retreive the message IDs that we'll look for in WndProc
				_MsgID_MouseLL = RegisterWindowMessage("WILSON_HOOK_MOUSELL");
				_MsgID_MouseLL_HookReplaced = RegisterWindowMessage("WILSON_HOOK_MOUSELL_REPLACED");

				// Start the hook
				InitializeMouseLLHook(0, _Handle);
			}

			protected override void OnStop()
			{
				UninitializeMouseLLHook();
			}

			public override void ProcessWindowMessage(ref System.Windows.Forms.Message m)

			{
				if (m.Msg == _MsgID_MouseLL)
				{
					if (MouseLLEvent != null)
						MouseLLEvent(m.WParam, m.LParam);

					MSLLHOOKSTRUCT M = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(m.LParam, typeof(MSLLHOOKSTRUCT));

					if (m.WParam.ToInt32() == WM_MOUSEMOVE)
					{
						if (MouseMove != null)
							MouseMove(this, new MouseEventArgs(MouseButtons.None, 0, M.pt.X, M.pt.Y, 0));
					}
					else if (m.WParam.ToInt32() == WM_LBUTTONDOWN)
					{
						if (MouseDown != null)
							MouseDown(this, new MouseEventArgs(MouseButtons.Left, 0, M.pt.X, M.pt.Y, 0));
					}
					else if (m.WParam.ToInt32() == WM_RBUTTONDOWN)
					{
						if (MouseDown != null)
							MouseDown(this, new MouseEventArgs(MouseButtons.Right, 0, M.pt.X, M.pt.Y, 0));
					}
					else if (m.WParam.ToInt32() == WM_LBUTTONUP)
					{
						if (MouseUp != null)
							MouseUp(this, new MouseEventArgs(MouseButtons.Left, 0, M.pt.X, M.pt.Y, 0));
					}
					else if (m.WParam.ToInt32() == WM_RBUTTONUP)
					{
						if (MouseUp != null)
							MouseUp(this, new MouseEventArgs(MouseButtons.Right, 0, M.pt.X, M.pt.Y, 0));
					}
				}
				else if (m.Msg == _MsgID_MouseLL_HookReplaced)
				{
					if (HookReplaced != null)
						HookReplaced();
				}
			}
		}
		public class CallWndProcHook : Hook
		{
			// Values retreived with RegisterWindowMessage
			private int _MsgID_CallWndProc;
			private int _MsgID_CallWndProc_Params;
			private int _MsgID_CallWndProc_HookReplaced;

			public event HookReplacedEventHandler HookReplaced;
			public event WndProcEventHandler CallWndProc;

			private IntPtr _CacheHandle;
			private IntPtr _CacheMessage;

			public CallWndProcHook(IntPtr Handle) : base(Handle)
			{
			}

			protected override void OnStart()
			{
				// Retreive the message IDs that we'll look for in WndProc
				_MsgID_CallWndProc_HookReplaced = RegisterWindowMessage("WILSON_HOOK_CALLWNDPROC_REPLACED");
				_MsgID_CallWndProc = RegisterWindowMessage("WILSON_HOOK_CALLWNDPROC");
				_MsgID_CallWndProc_Params = RegisterWindowMessage("WILSON_HOOK_CALLWNDPROC_PARAMS");

				// Start the hook
				InitializeCallWndProcHook(0, _Handle);
			}

			protected override void OnStop()
			{
				UninitializeCallWndProcHook();
			}

			public override void ProcessWindowMessage(ref System.Windows.Forms.Message m)
			{
				if (m.Msg == _MsgID_CallWndProc)
				{
					_CacheHandle = m.WParam;
					_CacheMessage = m.LParam;
				}
				else if (m.Msg == _MsgID_CallWndProc_Params)
				{
					if (CallWndProc != null && _CacheHandle != IntPtr.Zero && _CacheMessage != IntPtr.Zero)
						CallWndProc(_CacheHandle, _CacheMessage, m.WParam, m.LParam);
					_CacheHandle = IntPtr.Zero;
					_CacheMessage = IntPtr.Zero;
				}
				else if (m.Msg == _MsgID_CallWndProc_HookReplaced)
				{
					if (HookReplaced != null)
						HookReplaced();
				}
			}
		}
		public class GetMsgHook : Hook
		{
			// Values retreived with RegisterWindowMessage
			private int _MsgID_GetMsg;
			private int _MsgID_GetMsg_Params;
			private int _MsgID_GetMsg_HookReplaced;

			public event HookReplacedEventHandler HookReplaced;
			public event WndProcEventHandler GetMsg;

			private IntPtr _CacheHandle;
			private IntPtr _CacheMessage;

			public GetMsgHook(IntPtr Handle) : base(Handle)
			{
			}

			protected override void OnStart()
			{
				// Retreive the message IDs that we'll look for in WndProc
				_MsgID_GetMsg_HookReplaced = RegisterWindowMessage("WILSON_HOOK_GETMSG_REPLACED");
				_MsgID_GetMsg = RegisterWindowMessage("WILSON_HOOK_GETMSG");
				_MsgID_GetMsg_Params = RegisterWindowMessage("WILSON_HOOK_GETMSG_PARAMS");

				// Start the hook
				InitializeGetMsgHook(0, _Handle);
			}

			protected override void OnStop()
			{
				UninitializeGetMsgHook();
			}

			public override void ProcessWindowMessage(ref System.Windows.Forms.Message m)
			{
				if (m.Msg == _MsgID_GetMsg)
				{
					_CacheHandle = m.WParam;
					_CacheMessage = m.LParam;
				}
				else if (m.Msg == _MsgID_GetMsg_Params)
				{
					if (GetMsg != null && _CacheHandle != IntPtr.Zero && _CacheMessage != IntPtr.Zero)
						GetMsg(_CacheHandle, _CacheMessage, m.WParam, m.LParam);
					_CacheHandle = IntPtr.Zero;
					_CacheMessage = IntPtr.Zero;
				}
				else if (m.Msg == _MsgID_GetMsg_HookReplaced)
				{
					if (HookReplaced != null)
						HookReplaced();
				}
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Burkina Faso Burkina Faso
I currently live in a small town in Burkina Faso, where I spend some of my free time (during the hours when there's electricity) playing around with C#. For a bit more about my less nerdy activities, check out http://chrisburkina.blogspot.com or http://www.youtube.com/watch?v=Rw1Pb7hlIWw -- neither of them, however, has anything to do with C#.

Comments and Discussions