前言:最近在寫一個桌面程序時需要全局HOOK 窗體的創(chuàng)建芙粱,但是在.net中SetWindowsHookEx()只可實現(xiàn)鍵盤鼠標(biāo)的全局鉤子,其余的全局鉤子都需要使用DLL。難道就沒有解決辦法了么央串?經(jīng)過長時間的搜索后在CSDN的一篇帖子中,有大神提到了RegisterShellHookWindow()這個方法偷溺。但是又經(jīng)過一番搜索后蹋辅,發(fā)現(xiàn)基本上是C++或者其他語言的使用分享。所以寫下了這篇文章挫掏,給后來的人提供快速解決的途徑侦另。
在WinForm中使用RegisterShellHook
1.準(zhǔn)備工作
......
[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.注冊鉤子
- 注意事項:不要在構(gòu)造函數(shù)中注冊鉤子,此時窗體的handle未被創(chuàng)建尉共。
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("窗體創(chuàng)建");
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.準(zhǔn)備工作
[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("窗體被創(chuàng)建");
break;
}
}
return IntPtr.Zero;
}
4.卸載鉤子
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
DeregisterShellHookWindow(handle);
}