C# 中使用RegisterShellHookWindow Hook窗体创建
前言:最近在写一个桌面程序时需要全局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窗体创建的更多相关文章
- Dynamics CRM2013 从subgrid中打开快速创建窗体创建数据
在页面上使用subgrid时,在subgrid中新建数据时需要跳转到另一个页面,这种操作比较麻烦且很不友好,这时我们想到了快速创建窗体,像下图这样直接在当前页上方下拉出现一个窗体,填写内容后点击保存就 ...
- 在DLL中封装的VCL窗体Tab键响应的问题
在DLL中的子窗体不会响应Tab按键的,这个时候就需要手动去指定Tab键的操作,但是前提是主窗体要向这个窗体发送一个消息,一个Tab键按下的消息.基本顺序是这样的: 1. 主窗体用Hook技术捕获Ta ...
- delphi 中封装的VCl窗体Tab键响应问题
在DLL中的子窗体不会响应Tab按键的,这个时候就需要手动去指定Tab键的操作,但是前提是主窗体要向这个窗体发送一个消息,一个Tab键按下的消息.基本顺序是这样的: 1. 主窗体用Hook技术捕获Ta ...
- Delphi中实现MDI子窗体(转)
Delphi中实现MDI子窗体 用MDI实现浏览子窗口,具有窗口管理功能,同屏观看多个网页的内容 ① 多文档窗体(MDI) MDI窗体是一种具有主子结构的窗体体系,微软的Word便是其中的一 ...
- DevExpress中,添加Winform窗体到DockPanel z
DevExpress中,添加Winform窗体到DockPanel // 在使用DevExpress过程中,原先已经创建好的导航窗体,如何添加到DockPanel中进行展示? FormX frmX = ...
- Delphi窗体创建释放过程及单元文件小结(转)
Delphi窗体创建释放过程及单元文件小结 Delphi中的窗体,有模式窗体与非模式窗体两种.两种窗体的调用方式不同,模式窗体使用ShowModal显示,非模式窗体使用Show显示.当显示模式窗体的时 ...
- 深入解析Windows窗体创建和消息分发
Windows GUI採用基于事件驱动的编程模型,其实差点儿全部的界面库都是这样做的.在纯粹的Window32 SDK编程时代.人们还能够搞懂整个Windows窗口创建和消息的流通过程.可是在如今各种 ...
- 开发中常用的Hook
开发中常用的Hook 什么是Hook? Hook 是一些可以让你在函数组件里"钩入" React state 及生命周期等特性的函数,用来实现一些 class 组件的特性的. 1 ...
- Winform中如何实现父窗体传递数据到子窗体并刷新子窗体
原理:利用委托和事件,本文将以图文并茂的例子讲述,告诉我们So Easy --------------------------------------------------------------- ...
随机推荐
- MySQL连表查询练习题
1.建库 库名:linux50 字符集:utf8 校验规则:utf8_general_ci  create database linux4 charset utf8 default collate ...
- fragment事务 的基本处理
处理fragment事务 动态加载fragmentMyFragment2 fragment2=new MyFragment2();//new出一个fragment对象FragmentManager f ...
- 6.Shell 计划任务服务程序
计划任务服务程序 经验丰富的系统运维工程师可以使得Linux在无需人为介入的情况下,在指定的时间段自动启用或停止某些服务或命令,从而实现运维的自动化. 如何设置服务器的计划任务服务,把周期性.规律性的 ...
- KMP算法查找字符串
假设长字符串为t,短字符串为p.为了进行KMP匹配,首先需要计算字符串p的next数组,后面实现了计算该数组的函数void KmpGenNext(char* p, int* next).对于”abca ...
- C++虚函数作用原理(一)——虚函数如何在C++语言逻辑中存在
C++多态,接触其实也没太长的时间.上课的时候老师总是不停的讲,多态可以实现利用一个基类对象调用不同继承类的成员函数.我就会觉得很伤脑筋,这个的原理到底是什么?是什么呢? 开始的时候我觉得自己应该能够 ...
- Some ArcGIS Tools
在矢量叠加,即将同一区域.同一比例尺的两组或两组以上的多边形要素的数据文件进行叠加产生一个新的数据层,其结果综合了原来图层所具有的属性.矢量叠加操作分为:交集(Intersect).擦除(Erase) ...
- P2664 树上颜色统计 点分治 虚树 树上差分 树上莫队
树上差分O(n)的做法 考虑每种颜色对每个点的贡献,如果对于每种颜色我们把当前颜色的点删除,那么原来的树就会分成几个子树,对于一个点,当前颜色在和他同子树的点的点对路径上是不会出现的.考虑到有多种颜色 ...
- CSS如何水平垂直居中?
CSS如何水平垂直居中? 1.CSS如何实现水平居中? margin: 0 auto 2.CSS如何实现水平垂直居中? 首先设置一个div元素,设置背景颜色以便看出变化.代码如下: <!DOCT ...
- loj2718 「NOI2018」归程[Kruskal重构树+最短路]
关于Kruskal重构树可以翻阅本人的最小生成树笔记. 这题明显裸的Kruskal重构树. 然后这题限制$\le p$的边不能走,实际上就是要满足走最小边权最大的瓶颈路,于是跑最大生成树,构建Krus ...
- ngnix之笔记
############################################################################# 我们在使用的时候会遇到很多的恶意IP攻击,这 ...