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 --------------------------------------------------------------- ...
随机推荐
- kbmMemTable中怎么根据UniqueRecID定位到对应的记录
function TForm5.LocateUniqueRecID(aDataSet: TkbmMWCustomClientQuery; AID: TkbmNativeInt): Boolean; v ...
- smbfs
Hi I tried to mount a network share (smbfs) but it complains about the lack of kernel support. To so ...
- 【wifi移植 2】 移植wpa_supplicant
参考文章: http://bbs.eeworld.com.cn/thread-447273-1-1.html(加精作品) 1. 下载源码 下载wpa_supplicant-2.2.tar(openss ...
- GitHub的本地与远程
首先要有一个github账户(这不是废话吗) 在linux中先安装git arch linux : pacman -S git 在终端里输入 ssh-keygen ##一直默认就可以了 将公钥加入到G ...
- 卸载CUDA和cuDNN
卸载CUDA和cuDNN 1.卸载CUDA 本教程只针对对于.run方式安装的,其他的没有进行测试 打开终端,输入sudo /usr/local/cuda-10.0/bin/uninstall_cud ...
- Hive压缩和存储(十二)
压缩和存储 1. Hadoop压缩配置 1) MR支持的压缩编码 压缩格式 工具 算法 文件扩展名 是否可切分 DEFAULT 无 DEFAULT .deflate 否 Gzip gzip DEFAU ...
- 复杂sql优化步骤与技巧
数据管理型系统,由于用户的要求或者系统设计要求,会出现大量表进行join,还要进行大量统计性数据查询展示,甚至数据权限控制等操作.最后会导致sql异常复杂,随着数据量增加,或者只是应用到生产环境(正式 ...
- 用锁实现SQLSERVER中简单并发控制(转)
研究Oracle的同学都知道,Oracle的select语句中可以使用for update或者for update nowait来控制并发,这一功能可以使开发人员轻易的将锁定控制在会话级+行级,可以说 ...
- x86和x64下指针的大小
根据测试 int main() { ; )); )); int n1 = sizeof(a); int n2 = sizeof(p); // int n3 = sizeof(*p); error in ...
- docker 部署springcloud Feign组件无法访问问题
如题: docker部署后的服务注册ID是这样的. 这导致了Feign在调用其他组件的时候访问不到. 解决: 在docker部署指令添加EUREKA_INSTANCE_IP-ADDRESS=[你的IP ...