前言:最近在写一个桌面程序时需要全局HOOK 窗体的创建,但是在.net中SetWindowsHookEx()只可实现键盘鼠标的全局钩子,其余的全局钩子都需要使用DLL。难道就没有解决办法了么?经过长时间的搜索后在CSDN的一篇帖子中,有大神提到了RegisterShellHookWindow()这个方法。但是又经过一番搜索后,发现基本上是C++或者其他语言的使用分享。所以写下了这篇文章,给后来的人提供快速解决的途径。
在WinForm中使用RegisterShellHook
1.准备工作
...... [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern bool RegisterShellHookWindow(IntPtr hWnd); [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern uint RegisterWindowMessage(string Message); [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern bool DeregisterShellHookWindow(IntPtr hHandle); ...... uint WM_ShellHook; public enum ShellEvents { HSHELL_WINDOWCREATED = 1, HSHELL_WINDOWDESTROYED = 2, HSHELL_ACTIVATESHELLWINDOW = 3, HSHELL_WINDOWACTIVATED = 4, HSHELL_GETMINRECT = 5, HSHELL_REDRAW = 6, HSHELL_TASKMAN = 7, HSHELL_LANGUAGE = 8, HSHELL_SYSMENU = 9, HSHELL_ENDTASK = 10, HSHELL_ACCESSIBILITYSTATE = 11, HSHELL_APPCOMMAND = 12, HSHELL_WINDOWREPLACED = 13, HSHELL_WINDOWREPLACING = 14, HSHELL_HIGHBIT = 0x8000, HSHELL_FLASH = (HSHELL_REDRAW | HSHELL_HIGHBIT), HSHELL_RUDEAPPACTIVATED = (HSHELL_WINDOWACTIVATED | HSHELL_HIGHBIT) }
2.注册钩子
- 注意事项:不要在构造函数中注册钩子,此时窗体的handle未被创建。
private void Form1_Load(object sender, EventArgs e) { if (RegisterShellHookWindow(this.Handle)) { WM_ShellHook = RegisterWindowMessage("SHELLHOOK"); } }
3.处理消息
protected override void WndProc(ref Message m) { if (m.Msg == WM_ShellHook) { switch ((ShellEvents)m.WParam) { case ShellEvents.HSHELL_WINDOWCREATED: Console.WriteLine("窗体创建"); break; default: break; } } base.WndProc(ref m); }
4.卸载钩子
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { DeregisterShellHookWindow(this.Handle); }
在WPF中使用RegisterShellHook
- WPF较为特殊,handle不能直接取得,WndProc方法不能直接重写。
1.准备工作
[DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern bool RegisterShellHookWindow(IntPtr hWnd); [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern uint RegisterWindowMessage(string Message); [DllImport("User32.dll", CharSet = CharSet.Auto)] public static extern bool DeregisterShellHookWindow(IntPtr hHandle); public enum ShellEvents { HSHELL_WINDOWCREATED = 1, HSHELL_WINDOWDESTROYED = 2, HSHELL_ACTIVATESHELLWINDOW = 3, HSHELL_WINDOWACTIVATED = 4, HSHELL_GETMINRECT = 5, HSHELL_REDRAW = 6, HSHELL_TASKMAN = 7, HSHELL_LANGUAGE = 8, HSHELL_SYSMENU = 9, HSHELL_ENDTASK = 10, HSHELL_ACCESSIBILITYSTATE = 11, HSHELL_APPCOMMAND = 12, HSHELL_WINDOWREPLACED = 13, HSHELL_WINDOWREPLACING = 14, HSHELL_HIGHBIT = 0x8000, HSHELL_FLASH = (HSHELL_REDRAW | HSHELL_HIGHBIT), HSHELL_RUDEAPPACTIVATED = (HSHELL_WINDOWACTIVATED | HSHELL_HIGHBIT) } uint WM_ShellHook;
2.注册钩子
private IntPtr handle; public MainWindow() { InitializeComponent(); this.SourceInitialized += new EventHandler(Win_SourceInitialized); } private void Window_Loaded(object sender, RoutedEventArgs e) { handle = new WindowInteropHelper(this).Handle; if (RegisterShellHookWindow(handle)) { WM_ShellHook = RegisterWindowMessage("SHELLHOOK"); } } private void Win_SourceInitialized(object sender, EventArgs e) { HwndSource source = PresentationSource.FromVisual(this) as HwndSource; if (source != null) source.AddHook(WndProc); }
3.处理消息
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg == WM_ShellHook) { switch ((ShellEvents)wParam) { case ShellEvents.HSHELL_WINDOWCREATED: Console.WriteLine("窗体被创建"); break; } } return IntPtr.Zero; }
4.卸载钩子
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { DeregisterShellHookWindow(handle); }