前言:最近在写一个桌面程序时需要全局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. Oracle 11.2.0.1 ADG环境MRP进程遭遇ORA

    环境:Linux + Oracle 11.2.0.1 ADG现象:发现备库没有应用日志 1. 数据库查询备库目前状态发现备库目前没有应用日志,apply lag已经显示备库有3天21小时多没有应用日志 ...

  2. C# 基础 字符串 集合 文件操作

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. Python map学习笔记

    map是一个高阶用法,字面意义是映射,它的作用就是把一个数据结构映射成另外一种数据结构. map用法比较绕,最好是对基础数据结构很熟悉了再使用,比如列表,字典,序列化这些. map的基本语法如下: m ...

  4. 九,configMap及secret的基本使用

    目录 制定容器配置的方式 configMap(存储数据为明文,敏感数据慎用) 创建configMap的几种方式 命令行创建和测试configMap实例 创建一个Pod 挂载测试 通过指定文件创建con ...

  5. python常有模块:模块、引入语法、两种执行方式、模块搜索顺序

    今天主要讲了以下几点:一.模块三问.定义及分类二.import和from的语法三.文件的两种执行方式及搜索顺序四.内置函数 一.模块.import和from的语法 1.什么是模块   模块是一堆功能函 ...

  6. C++归并排序(数组&链表)

    1.归并排序(Merge Sort) 归并排序的性能不受输入数据的影响,始终都是O(n log n)的时间复杂度.代价是需要额外的内存空间. 归并排序是建立在归并操作上的一种有效的排序算法.该算法是采 ...

  7. 数据防泄密(DLP)

    数据防泄密(DLP)近几年已经成为国内非常热门的关键词. 目前市场上DLP产品主要可以分为三大类,各类产品都来源于不同的技术体系,防护效果也各有优缺点. 第一类,以监控审计为主,对进出的数据进行过滤, ...

  8. java——比较难和底层的面试题

    链接地址:https://mp.weixin.qq.com/s/lnbCysCQgfjF_kcB83KQZg 这是一个在线教育机构的文章,感觉大部分都不会,太难了. 一.自我介绍 二.多线程相关: 线 ...

  9. 22_5mybatis多表操作

    1.表之间的关系 一对多 多对一 一对一 多对多 举例: 用户和订单就是一对多 订单和用户就是多对一 一个用户可以下多个订单 多个订单属于同一个用户 人和身份证号就是一对一 一个人只能有一个身份证号 ...

  10. python和ruby:一些需要注意的小区别。

    python和ruby的一些区别 基础区别 运算符号/和// ruby只有/符号.它根据操作的数字类型返回对应的结果.如果数字的类型是int,则返回整除结构,如果是float,则返回float类型的计 ...