前言:最近在写一个桌面程序时需要全局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. Nginx作为静态资源web服务之防盗链

    Nginx作为静态资源web服务之防盗链 首先,为什么需要防盗链,因为有些资源存在竞争对手的关系,比如淘宝的商品图片,不会轻易的让工具来爬虫爬走收集.但是如果使用防盗链,需要知道上一个访问的资源,然后 ...

  2. 7.Hibernate查询

    一:Hibernate可以使用的查询语言 1.NativeSQL:本地语言(数据库自己的SQL语句) 2.HQL:hibernate自带的查询语句,可以使用HQL语言,转换成具体的方言 3.EJBQL ...

  3. MySQL的左连接查询,只取出最大的一条数据

    今天有个需求,是通过两张表进行查询.一对多的关系.通过一个主键,取出其中的一条.开始以为还好,直接用用了left join on进行查询.却发现了问题所在.其他的好弄.开始的写法借鉴这篇博客:http ...

  4. 修改tomcat 端口

    假设tomcat所在目录为/usr/local/apache-tomcat/ 1.打开tomcat配置文件#vi /usr/local/apache-tomcat/conf/server.xml 2. ...

  5. Easy Populate批量管理下载产品数据为空的解决办法

    把原来的先删除:http://aaaaacom/admin/easypopulate.php?langer=remove

  6. BZOJ 1015 并查集&连通块

    很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的以太隧道互相直接或 ...

  7. 使用curl出现,curl: /usr/local/lib/libssl.so.1.1: version `OPENSSL_1_1_1' not found (required by /usr/lib/x86_64-linux-gnu/libcurl.so.4)

    主要原因是curl找不到openssl的路径,所以只要将openssl的路径添加到相应的变量中就可以了. 参考连接https://blog.csdn.net/RookieWutongshu/artic ...

  8. CF892E Envy[最小生成树]

    题意:有一张 $n$ 个点$ m $条边的连通图.有$Q$ 次询问.每次询问给出 $k[i]$ 条边,问这些边能否同时出现在一棵最小生成树上.$n,m,Q,\sum k\le 500000$. 这题利 ...

  9. vue插件——滚动监听 vue-scrollwatch

    造轮子的目的: 做项目的时候需要一个滚动监听的功能,html结构已经都写好了,不想使用vue组件的方式来写,因为不想改造html结构,于是花了几个小时做了一个简单的,使用vue指令方式来做的,项目上够 ...

  10. BZOJ 2119: 股市的预测 (Hash / 后缀数组 + st表)

    转博客大法好 自己画一画看一看,就会体会到这个设置关键点的强大之处了. CODE(sa) O(nlogn)→1436msO(nlogn)\to 1436msO(nlogn)→1436ms #inclu ...