最近工作中遇到Window Ghosting这个问题, 感觉挺有意思,这里简单记录下。
在XP时代我们的程序没有响应后只能通过任务管理器强制杀掉,但是Vista之后情况变了, 我们仍然可以拖动失去响应的窗口,甚至可以尝试最小化和关闭窗口, 我们把这个特性叫住Window Ghosting。
首先我们考虑下怎样判断一个窗口是否已经失去响应?
一般我们想到的是SendMessageTimeout,给窗口发送WM_NULL消息,判断返回是否超时。这当然也是一种方法,但是系统有更方便的API  IsHungAppWindow, 该API是判断窗口是否失去响应的标准方法。我们猜测IsHungAppWindow内部是否通过SendMessageTimeout来实现的, 跟踪下我们会发现不是我们想象的那样, IsHungAppWindow内部掉用了未公开的API NtUserQueryWindow。
接下来考虑下  IsHungAppWindow 是如何鉴定一个窗口是否在失去响应状态?
这是MSDN中的原话: 
Determines whether the system considers that a specified application is not responding. An application is considered to be not responding if it is not waiting for input, is not in startup processing, and has not called PeekMessage  within the internal timeout period of 5 seconds.
简单来说就是程序在非等待输入状态 ,不是在程序启动阶段, 并且5秒内没有从消息队列中取消息。 
下面我们思考系统是如何实现Window Ghosting的?
我们知道失去响应的窗口一般来说是因为UI线程正在做一些繁忙的工作, 或是UI线程死锁而没有在继续运行了。 那这里就很奇怪了, UI线程都失去响应了, 窗口怎么还能响应我们的鼠标拖动消息?我们的鼠标拖动事件需要运行在UI线程中才行 ,该实现有些颠覆我们现有的计算机知识。
这里的关键就是我们看到的失去响应的窗口是不是还是我们原来的窗口? 实际上我们真正的窗口已经让系统用Ghosting窗口替代了。
完整过程是这样的, 当系统检测到我们程序窗口失去响应了, 系统进程(dwm.exe)会以相同的Z-order, 位置,大小和Style创建一个ghosting窗口(可以通过SPY查看 ,类名是Ghost), 我 们看到的失去响应的窗口就是这个窗口, 该窗口的客户区内容是从老窗口中拷贝过来的。而我们原来真正窗口依旧在那里(style, 位置,大小和z-order都没有变 ), 但是dwm.exe合成屏幕内容是并不会把这个窗口画出来, 所以我们看起来就是原来的窗口给hide了。
这就是Window Ghosting的奥秘, 我们可以在程序中调用 API DisableProcessWindowsGhosting 来禁止系统对我们的程序使用 Window Ghosting.
Window Ghosting这个特性很不错, 让失去响应的程序也有很好的用户体验, 但是它也带来了一些问题。
我遇到的问题是我们在枚举窗口的过程中,我们通过GetWindowRect查询一个失去响应的程序窗口的位置,但是返回结果却和我们屏幕上看到的不一致, 因为我们看到的是被我们拖动过的Ghosting window,但是API返回的确是被hide的原窗口的位置。 这种情况下我们需要原窗口和Ghosting窗口的一张映射表, 但是我还没有找到他们对应关系的方法, 不知道系统又没有相关API提供?一种方法是通过查找类名是"Ghost"的窗口,判断进程是不是dwm.exe, 再通过标题匹配。但是该方法效率低,也不可靠。

转载于:https://www.cnblogs.com/weiym/p/3512680.html

Window Ghosting相关推荐

  1. 2021年大数据Flink(十八):Flink Window操作

    目录 ​​​​​​​Flink-Window操作 为什么需要Window Window的分类 按照time和count分类 ​​​​​​​按照slide和size分类 ​​​​​​​总结 Window ...

  2. Ipython的Window与Linux详细安装

    IPython 是一个 python 的交互式 shell,支持补全等等一些强大的功能: IPython 为交互式计算提供了一个丰富的架构,包含: 强大的交互式 shell Jupyter 内核 交互 ...

  3. window 10 桌面显示计算机的操作

    点击设置--个性化设置--主题--桌面图标设置--勾选即可 (这个个性化设置可以点击window右键点击可以,这个看自己的习惯.win7的计算机在win10叫此电脑) 下面放一些图片

  4. [skill] vim 操作多个window

    前言: 分辨率越来越高,屏幕越来越大,行最长80不变,屏幕利用空白越来越大. 开多个window吧! 开window的命令: 平行开一个window :split <//path/file> ...

  5. How to set window title name on Oracle EBS Form?

    --1. 置換掉原來Winodw Property上的Title String ex. SET_WINDOW_PROPERTY('XXDII_INV_MISC_TXN_V',TITLE,:misc_t ...

  6. JS中window.event事件使用详解

    一.描述 event代表事件的状态,例如触发event对象的元素.鼠标的位置及状态.按下的键等等. event对象只在事件发生的过程中才有效. event的某些属性只对特定的事件有意义.比如:from ...

  7. js 打开窗口window.open

    js改变原有的地址 window.open(webPath+'/index?code='+code,'_self'); 转载于:https://www.cnblogs.com/hwaggLee/p/4 ...

  8. 事件绑定在IE下this是window的问题

    昨天写一个函数的时候,后来用了事件绑定,开始没在IE下测试,在chrome下都是没问题的.后来在IE下测试发现出错. 后来修改一下,发现oBox.οnclick=function(){}没问题,而ad ...

  9. window对象提供的功能之窗口最大化

    实现窗口最大化的基本思路是:首先打开一个"中转"页面,在该页面中用window.open方法打开一个最大化的窗口,并且在该窗口中将父窗口关闭.实例如下: ex3.html: 代码 ...

最新文章

  1. Spark读取Hive中的数据加载为DataFrame
  2. 字符串与指针,数组的关系与用途
  3. 执行setenv ethaddr的时候提示Can't over write的原因及解决方法
  4. centos 6.5 openldap php,centos6.5安装openldap+phpldapadmin
  5. tomcat(10)安全性
  6. CVPR2021 | 北航商汤耶鲁口头报告
  7. RefreshLayout刷新组件,有详细注释适合使用和中高端学习
  8. 【答辩问题】计算机专业本科毕业设计答辩的一般程序2
  9. 郭宏志的android无线点餐系统,Android无线点餐系统--含代码.doc
  10. WebAPI——cookie与session遇到的问题
  11. 终于购入Mac mini,发现HDMI接口与显示器不兼容,网购了一个VGA转换插头
  12. PHP学习笔记【13】_正则表达式
  13. matlab 方差,方差分解——matlab 代码
  14. python3 调用http接口例子
  15. Android 渠道抽成,内容为主,渠道为辅,国内Android商店何时才能调整分成比?
  16. 关于BCM61650IFB1G
  17. 刷入magisk无限重启_手机刷成砖了?别慌,这些方法可以救回来
  18. 20个超炫的HTML5 /CSS3免费网页设计模板
  19. 数据库关于事务的详解分析(全)包含面试常问的细节
  20. do while循环

热门文章

  1. es文件管理连接ftp服务器,es文件浏览器访问ftp服务器
  2. 魔百和CM101S(魔百盒cm101s)刷机成功,奥利给!
  3. 《当幸福来敲门》有感
  4. ZDLJP型电子式精小型电动单座调节阀
  5. js实现groupby数组分组
  6. ROOK-02 优化集群参数部署ROOK
  7. 灵动微低功耗单片机MM32L0136C6P替换STM32L053C8
  8. 宋飞飞的全国计算机三级网络技术证书
  9. 京东家电今年将开上万家专卖店,线下PK苏宁国美
  10. 五款流行的PDF阅读器以及资源占用的对比