WPF 获取全局所有窗口的创建显示事件 监控窗口打开
本文将告诉大家如何在 WPF 里面进行全局监控任意的窗口创建显示打开,可以获取到每个 WPF 窗口的打开的时机。如此可以用来辅助定位问题和输出日志
这篇博客是有背景的,老司机告诉我说他的应用不响应鼠标和键盘点击了,于是我和他调查了半天才发现有一个 Dialog 窗口显示出来,导致消息循环被切到了一个 Dialog 窗口里面去了。然而这个 Dialog 窗口是藏起来的,在屏幕上刚好没有能看见他
此时我就好奇了,为什么我的应用就不会存在如此的逗比代码,但是老司机的应用就可能存在如此难以调试的问题。于是我就在自己的应用上写了一个逗比代码,强行弹出一个 Dialog 窗口出来,结果我就发现监控模块告诉了我有一个在白名单之外的窗口弹出了,如果确定这是符合开发预期的,那就需要手动修改白名单。这是一个开发时的辅助机制,用来让开发者不要随便弹出窗口,我又好奇这个监控模块是如何监控到我弹出一个窗口的,学习了监控模块的机制,就写了这个博客
在 WPF 里面,可以通过 EventManager 监听全局的路由事件,刚好窗口创建显示时,将会触发一些路径事件。通过路由事件监听,即可了解是哪个窗口正在准备弹出。于是就可以进行监控窗口创建显示
监听窗口的 SizeChangedEvent 路由事件是比较靠谱的方式,这个有一点点违反开发者的想法,开发者默认想的是使用 LoadedEvent 事件。但是在 WPF 里面做了一些性能优化,如果一个窗口没有 XAML 或者是没有任何代码监听了 Loaded 事件,那将不触发 LoadedEvent 路由事件。因此这里就监听窗口一定会触发的 SizeChangedEvent 事件
代码如下
public App()
{
EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent, new RoutedEventHandler(Window_OnLoaded));
EventManager.RegisterClassHandler(typeof(Window), Window.SizeChangedEvent, new RoutedEventHandler(Window_SizeChanged));
}
private void Window_OnLoaded(object sender, RoutedEventArgs e)
{
// 如果窗口没有 XAML 或者没有监听 Loaded 事件,将不会被触发
}
private void Window_SizeChanged(object sender, RoutedEventArgs e)
{
// 所有窗口都会触发
}
窗口创建的时候,将会进入 Window_SizeChanged 事件。通过 sender 参数即可了解是哪个窗口对象被创建,接着就可以方便进行日志或者是提示开发者不要随便创建窗口等
可以自己测试一下代码,例如在 MainWindow 里面再次创建一个空窗口
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
var window = new Window();
window.Show();
}
}
运行以上的代码,可以看到 Window_SizeChanged 被进入两次,分别是 MainWindow 和在 MainWindow 里面创建显示的窗口。而 Window_OnLoaded 只会进入一次,在 MainWindow 准备显示时进入
我推荐在自己的项目里面,在 Debug 下加上此机制,至少输出一下窗口显示的日志,方便了解显示了哪些窗口。如果可以的话,也可以加上白名单机制,如果一个窗口是新写的之类的,可以提示开发者阅读必要的文档之后加入到白名单里面。也可以在事件里面对每个窗口注入一些有趣的逻辑,或者是监听窗口的各个事件,输出更多日志,让开发者可以通过日志了解到当前有哪些窗口依然还在显示
这是另一位大佬写的代码,请看 https://gist.github.com/mwisnicki/3104963
WPF 获取全局所有窗口的创建显示事件 监控窗口打开的更多相关文章
- 获取全局上下文(getApplicationContext)_创建Shared Preference工具类_实现自动登录
获取全局上下文(getApplicationContext)_创建Shared Preference工具类_实现自动登录 ===========================获取全局上下文(getA ...
- uCGUI窗口的创建过程分析
一.相关结构体和变量 窗口管理结构体 /* 窗口管理结构体 共30个字节 */ struct WM_Obj { GUI_RECT Rect; //窗口尺寸(x0,y0,x1,y1) 8个字节 GUI_ ...
- Add an Action that Displays a Pop-up Window 添加显示弹出窗口按钮
In this lesson, you will learn how to create an Action that shows a pop-up window. This type of Acti ...
- 有谁知道Delphi中"窗口"的创建过程?
求助:有谁知道Delphi中窗口的创建过程,此“窗口”不仅仅指 TForm 类型, 还包括一般的窗口控件,如TButton,TEdit等等,希望有能够十分详细的运作 过程,比如说CreatPara ...
- system调用命令行命令而不显示命令行窗口
system调用命令行命令而不显示命令行窗口 通常用system调用命令行命令时都会弹出黑底白字的命令行窗口,下面的代码可以不显示弹出的命令行窗口. 代码如下 #pragma comment( lin ...
- Android窗口管理服务WindowManagerService对壁纸窗口(Wallpaper Window)的管理分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8550820 Android系统中,壁纸窗口和输 ...
- WPF 获取应用的所有窗口
原文:WPF 获取应用的所有窗口 本文告诉大家如何获取应用内的所有窗口,无论这些窗口有没显示 在 WPF 可以通过 Application.Current.Windows 列举应用的所有窗口 fore ...
- WPF 获取元素(Visual)相对于屏幕设备的缩放比例,可用于清晰显示图片
原文:WPF 获取元素(Visual)相对于屏幕设备的缩放比例,可用于清晰显示图片 我们知道,在 WPF 中的坐标单位不是屏幕像素单位,所以如果需要知道某个控件的像素尺寸,以便做一些与屏幕像素尺寸相关 ...
- QT+创建两个不相干的窗口实现一个显示一个不显示
因为两个窗口互不相干,所以需要重新创建一个窗口类subWidget subWidget.cpp文件 #ifndef SUBWIDGET_H #define SUBWIDGET_H #include & ...
- WPF 获取鼠标屏幕位置、窗口位置、控件位置
原文:WPF 获取鼠标屏幕位置.窗口位置.控件位置 public struct POINT { public int X; public int Y; public POINT(int x, int ...
随机推荐
- Redis 中 scan 命令太坑了,千万别乱用!!
作者:铂赛东\链接:www.jianshu.com/p/8cf8aac3dc25 1 原本以为自己对redis命令还蛮熟悉的,各种数据模型各种基于redis的骚操作.但是最近在使用redis的scan ...
- verilog之基本结构
verilog语法的基本结构 1.verilog的定义 verilog,一种硬件描述语言,致力于提高数字电路,尤其是大规模数字电路的描述规范.从描述就可以看出,这个语言和C不同,不是高级语言.但是,这 ...
- UE4Gameplay定时器
参考 定时器在全局定时器管理器(FTimerManager类)中管理,对于每个实例Uobject和场景都会有全局定时器管理器,一般来说通过SetTimer和SetTimerForNextTick来设置 ...
- 北京思特奇2023年校招笔试(Java)
北京思特奇2023年校招笔试(Java) 1.表达式 (short)10/10.2*2 运算后结果是什么类型? 答案:double,浮点数默认是double,自动类型向上转换为浮点数类型 2. ser ...
- DNS的各种记录类型的应用解析
可能很多人平时工作中不会遇到DNS配置相关的问题, 但如果偶尔遇到不同类型DNS记录的配置, 在没有搞清楚它们都是干啥的情况下, 会眼花缭乱, 还记得很多年前实验室配置DNS不太对导致只能访问www. ...
- #线性dp,排列组合#洛谷 2476 [SCOI2008]着色方案
题目 分析(弱化版) 最暴力的想法就是直接维护每种颜色的个数dp, 弱化版有一个很突出的地方就是 \(c_i\leq 5\), 也就是说可以将相同个数的颜色合并按照个数dp, 设 \(dp[c1][c ...
- DevEco Device Tool 助力OpenHarmony设备开发
DevEco Device Tool 为设备开发者提供一站式的开发环境和资源获取通道,实现了从芯片模板工程创建.到开发资源挑选定制,再到快速编码.轻小型系统调试调优.烧录环节的全流程覆盖,帮助开发者实 ...
- 深入了解 Python MongoDB 查询:find 和 find_one 方法完全解析
在 MongoDB 中,我们使用 find() 和 find_one() 方法来在集合中查找数据,就像在MySQL数据库中使用 SELECT 语句来在表中查找数据一样 查找单个文档 要从MongoDB ...
- 【FAQ】推送前台应用的通知处理功能没生效,如何进行排查?
一.前台应用的通知处理简介 在调用推送接口时可以设置"foreground_show"字段控制前台应用的通知栏消息是否通过NC展示."foreground_show&qu ...
- Godot UI线程,Task异步和消息弹窗通知
目录 前言 线程安全 全局消息IOC注入 消息窗口搭建 最简单的消息提示 简单使用 仿Element UI ElementUI 效果 简单的Label样式 如何快速加载多个相同节点 修改一下,IOC按 ...