最近工作中遇到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 calledPeekMessage 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, 再通过标题匹配。但是该方法效率低,也不可靠。

Window Ghosting的更多相关文章

  1. Window Ghosting(仍可拖动失去响应的窗口,因为我们真正的窗口已经让系统用Ghosting窗口替代了。使用IsHungAppWindow 探测)

    最近工作中遇到Window Ghosting这个问题, 感觉挺有意思,这里简单记录下.     在XP时代我们的程序没有响应后只能通过任务管理器强制杀掉,但是Vista之后情况变了, 我们仍然可以拖动 ...

  2. [虾扯蛋] android界面框架-Window

    从纯sdk及framwork的角度看,android中界面框架相关的类型有:Window,WindowManager,View等.下面就以这几个类为出发点来概览下安卓开发的"界面架构&quo ...

  3. JS判断鼠标进入容器方向的方法和分析window.open新窗口被拦截的问题

    1.鼠标进入容器方向的判定 判断鼠标从哪个方向进入元素容器是一个经常碰到的问题,如何来判断呢?首先想到的是:获取鼠标的位置,然后经过一大堆的if..else逻辑来确定.这样的做法比较繁琐,下面介绍两种 ...

  4. 谈谈document.ready和window.onload的区别

    在Jquery里面,我们可以看到两种写法:$(function(){}) 和$(document).ready(function(){}) 这两个方法的效果都是一样的,都是在dom文档树加载完之后执行 ...

  5. X Window 的奥秘

    大名鼎鼎的 X Window 大家肯定不陌生.都知道它是 Unix/Linux 下面的窗口系统,也都知道它基于 Server/Clinet 架构.在网上随便搜一搜,也可以找到不少 X Window 的 ...

  6. Android Starting Window(Preview Window)

    当打开一个Activity时,如果这个Activity所属的应用还没有在运行,系统会为这个Activity所属的应用创建一个进程,但进程的创建与初始化都需要时间,在这个动作完成之前系统要做什么呢?如果 ...

  7. JavaScript权威设计--Window对象之Iframe(简要学习笔记十四)

    1.Window对象属性的文档元素(id) 如果在HTML文档中用id属性来为元素命名,并且如果Window对象没有此名字的属性,Window对象会赋予一个属性,它的名字是id属性的值,而他们的值指向 ...

  8. JavaScript权威设计--Window对象(简要学习笔记十三)

    1.Window对象是所有客户端JavaScript特性和API的主要接入点. Window对象中的一个重要属性是document,它引用Document对象. JavaScript程序可以通过Doc ...

  9. $(document).ready() 与window.onload的区别

    1.执行时间 window.onload必须等到页面内包括图片的所有元素加载完毕后才能执行. $(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕. 2.编写个数不同 ...

随机推荐

  1. SQL语句性能测试

    /* --Sqlserver 清楚执行缓存, 用于SQL语句性能测试 DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE */

  2. 下载Spring框架开发包

    1.打开官网: http://spring.io/,打开project >> spring framework 2.在右侧找到要用的版本,如4.3.4,打开reference,搜索&quo ...

  3. 跟我学-Java底层技术系列文章

    对于工作中经常用到的东西,还是多看看实现原理,这样用着才能放心. 源码思想学习计划: 1.java基础库  HashCode深入理解 java线程框架窥探 2.集合类     java枚举类使用 递归 ...

  4. XML解析、使用TreeView呈现效果

    首先用到TXMLDocument控件: Memo来显示XML文件, TreeView来呈现元素: 源代码: Procedure TForm2.Button1Click(Sender: TObject) ...

  5. 关于echarts3地图下钻省市

    最近关于echarts3弄了个地图下钻,也许是因为运气不好,开始上来需要传递到的城市是成都,结果成都地图(js)加载下来总是挤到了一起,好尴尬,各方实验查找后发现原来是js文件中,成都市地图有个县市并 ...

  6. 除法取模练习(51nod 1119 & 1013 )

    题目:1119 机器人走方格 V2 思路:求C(m+n-2,n-1) % 10^9 +7       (2<=m,n<= 1000000) 在求组合数时,一般都通过双重for循环c[i][ ...

  7. 关于session和token

       最近做的项目是全平台的,需要给移动端做后台,有了许多改变,如是使用token而不是session.一开始我无法理解为什么不用session,看了很多文章以后才有一定了解.    例如在ios端, ...

  8. 今天我们要说的画一个三角形,恩,画一个三角形,第一种呢是利用我们的html标签结合css来实现;而第二种方法就就是我们的html5新增的一个标签canves,这个canves就是网页画幕,那么顾名思义就是在网页里建造一个画板,用来画画,好,那接下来就和我一起去看看吧!

    第一种方法:利用我们的html标签结合css来实现 span{ width:0px; height:0px; border-width:7px; border-style:solid; border- ...

  9. 转 :meta name的含义:<META http-equiv=Content-Type content="text/html; charset=gb2312">

    meta是什么?meta其实是html语言head区的一个辅助性标签.在几乎所有的网页里,我们都可以看到类似下面这段html代码:<META http-equiv=Content-Type co ...

  10. setenv.bat

    @echo off rem Licensed to the Apache Software Foundation (ASF) under one or more rem contributor lic ...