前言:最近在写一个桌面程序时需要全局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 = ,
HSHELL_WINDOWDESTROYED = ,
HSHELL_ACTIVATESHELLWINDOW = ,
HSHELL_WINDOWACTIVATED = ,
HSHELL_GETMINRECT = ,
HSHELL_REDRAW = ,
HSHELL_TASKMAN = ,
HSHELL_LANGUAGE = ,
HSHELL_SYSMENU = ,
HSHELL_ENDTASK = ,
HSHELL_ACCESSIBILITYSTATE = ,
HSHELL_APPCOMMAND = ,
HSHELL_WINDOWREPLACED = ,
HSHELL_WINDOWREPLACING = ,
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 = ,
HSHELL_WINDOWDESTROYED = ,
HSHELL_ACTIVATESHELLWINDOW = ,
HSHELL_WINDOWACTIVATED = ,
HSHELL_GETMINRECT = ,
HSHELL_REDRAW = ,
HSHELL_TASKMAN = ,
HSHELL_LANGUAGE = ,
HSHELL_SYSMENU = ,
HSHELL_ENDTASK = ,
HSHELL_ACCESSIBILITYSTATE = ,
HSHELL_APPCOMMAND = ,
HSHELL_WINDOWREPLACED = ,
HSHELL_WINDOWREPLACING = ,
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);
}

引用:简书 C# 中使用RegisterShellHookWindow Hook窗体创建

C# 中使用RegisterShellHookWindow Hook窗体创建的更多相关文章

  1. Dynamics CRM2013 从subgrid中打开快速创建窗体创建数据

    在页面上使用subgrid时,在subgrid中新建数据时需要跳转到另一个页面,这种操作比较麻烦且很不友好,这时我们想到了快速创建窗体,像下图这样直接在当前页上方下拉出现一个窗体,填写内容后点击保存就 ...

  2. 在DLL中封装的VCL窗体Tab键响应的问题

    在DLL中的子窗体不会响应Tab按键的,这个时候就需要手动去指定Tab键的操作,但是前提是主窗体要向这个窗体发送一个消息,一个Tab键按下的消息.基本顺序是这样的: 1. 主窗体用Hook技术捕获Ta ...

  3. delphi 中封装的VCl窗体Tab键响应问题

    在DLL中的子窗体不会响应Tab按键的,这个时候就需要手动去指定Tab键的操作,但是前提是主窗体要向这个窗体发送一个消息,一个Tab键按下的消息.基本顺序是这样的: 1. 主窗体用Hook技术捕获Ta ...

  4. Delphi中实现MDI子窗体(转)

        Delphi中实现MDI子窗体 用MDI实现浏览子窗口,具有窗口管理功能,同屏观看多个网页的内容  ① 多文档窗体(MDI) MDI窗体是一种具有主子结构的窗体体系,微软的Word便是其中的一 ...

  5. DevExpress中,添加Winform窗体到DockPanel z

    DevExpress中,添加Winform窗体到DockPanel // 在使用DevExpress过程中,原先已经创建好的导航窗体,如何添加到DockPanel中进行展示? FormX frmX = ...

  6. Delphi窗体创建释放过程及单元文件小结(转)

    Delphi窗体创建释放过程及单元文件小结 Delphi中的窗体,有模式窗体与非模式窗体两种.两种窗体的调用方式不同,模式窗体使用ShowModal显示,非模式窗体使用Show显示.当显示模式窗体的时 ...

  7. 深入解析Windows窗体创建和消息分发

    Windows GUI採用基于事件驱动的编程模型,其实差点儿全部的界面库都是这样做的.在纯粹的Window32 SDK编程时代.人们还能够搞懂整个Windows窗口创建和消息的流通过程.可是在如今各种 ...

  8. 开发中常用的Hook

    开发中常用的Hook 什么是Hook? Hook 是一些可以让你在函数组件里"钩入" React state 及生命周期等特性的函数,用来实现一些 class 组件的特性的. 1 ...

  9. Winform中如何实现父窗体传递数据到子窗体并刷新子窗体

    原理:利用委托和事件,本文将以图文并茂的例子讲述,告诉我们So Easy --------------------------------------------------------------- ...

随机推荐

  1. scrapy命令:scrapy genspider详解 转

    当我们使用: scrapy startproject taobao 命令创建好scrapy蜘蛛后,你是否注意到,下面还有这么一行内容: F:\scrapyTest> scrapy startpr ...

  2. 正确理解这四个重要且容易混乱的知识点:异步,同步,阻塞,非阻塞,5种IO模型

    本文讨论的背景是Linux环境下的network IO,同步IO和异步IO,阻塞IO和非阻塞IO分别是什么 概念说明 在进行解释之前,首先要说明几个概念: - 用户空间和内核空间 - 进程切换 - 进 ...

  3. angular实现对百度天气api跨域请求

    申请秘钥:http://lbsyun.baidu.com/apiconsole/key  ,有个百度账号就行ak=开发者秘钥 url地址  :http://api.map.baidu.com/tele ...

  4. DataGrip导出查询结果数据

    1 按钮 2 选择保存位置即可

  5. django-spirt 论坛主题

    官方文档 新建项目 django_sprit 文件夹 cd django_sprit pip install django-spirit spirit startproject mysite cd m ...

  6. python异常:常见异常、处理、断言、自定义异常

    一.异常是什么 二.常见异常 三.异常处理 四.不太常用语法 五.主动判处异常 六.断言 七.使用场景 八.自定义异常类型 一.异常是什么 """ 什么是异常? 异常是错 ...

  7. zencart设置默认货币三种方法

    zencart设置默认货币为USD 方法一:mysql UPDATE configuration SET configuration_value = 'USD' WHERE configuration ...

  8. 【墨西哥区域赛】Carpet

    原题: 题意: 给你一个树,有1e5个节点,让你把这个树放在一个长1e6宽20的网格图里,要求一个格子放一个节点,树边之间不能相交 这是一道构造题 因为树的形状可能性很多,很复杂,所以不能简单猜测,而 ...

  9. 【洛谷P4172】水管局长

    题目大意:给定 N 个点,M 条边的无向图,支持两种操作:动态删边和查询任意两点之间路径上边权的最大值最小是多少. 题解: 引理:对原图求最小生成树,可以保证任意两点之间的路径上边权的最大值取得最小值 ...

  10. binlog2sql快速闪回

    https://github.com/danfengcao/binlog2sql 一.说明: DML(data manipulation language):       它们是SELECT.UPDA ...