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

http://www.cnblogs.com/weiym/p/3512680.html

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

  1. DrawerLayout建立侧滑时,显示侧滑页面,底层页面仍可以有点击响应,解决办法。

    第一感觉是下层仍有焦点,解决办法应该是侧方页面出现后,下层页面的焦点改为false,应该是动态去改变焦点的状态,但是不知道如何去实现. 然后再网上找到实现方法,感谢:http://blog.csdn. ...

  2. Android窗口管理服务WindowManagerService对壁纸窗口(Wallpaper Window)的管理分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8550820 Android系统中,壁纸窗口和输 ...

  3. Android窗口管理服务WindowManagerService对输入法窗口(Input Method Window)的管理分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8526644 在Android系统中,输入法窗口 ...

  4. 神逸之作:国产快速启动软件神品ALTRun

    http://xbeta.info/altrun.htm 作者: ET民工和塞壬 日期: 2010-09-15 分类: windows 标签: quick-launch <神逸之作:国产快速启动 ...

  5. 【vc】1_Windows程序内部运行机制

    创建一个Win32应用程序步骤: 1.编写WinMain函数; 2.创建窗口(步骤如下): a.设计(一个)窗口类(WNDCLASS) b.注册(该)窗口类. c.创建窗口. d.显示并更新窗口. 3 ...

  6. MFC 三种消息

    在MFC应用程序中传输的消息有三种类型:窗口消息.命令消息和控件通知. (1)窗口消息:WM_XXX 窗口消息(Window Message)一般与窗口的内部运作有关,如:创建窗口.绘制窗口和销毁窗口 ...

  7. MFC学习(二):消息映射

    1. 消息映射表的组成 宏DECLARE_MESSAGE_MAP,用在类的声明中,用来声明消息映射表. 宏BEGIN_MESSAGE_MAP,在使用类声明外,用来定义链接节点和填写链表节点中的数据,其 ...

  8. MFC学习(五)常见面试题

    1:应用程序类 CTestOneApp::InitInstance 可以看做是MFC程序的入口函数,main函数隐藏在这个函数中.实际开发中一般不需要对这个类进行操作,但如果要在建立主对话框之前处理一 ...

  9. windows程序内部运行机制

    Windows程序内部运行机制 2007-10-21 19:52 1010人阅读 评论(0) 收藏 举报 windowsvc++applicationcallbackwinapistructure W ...

随机推荐

  1. 华为u8800+ root 还是不能删除自带软件

    下载个RE文件管理器 进入RE文件管理器后把上面的只读改成读写(ROOT过的点一下上面的只读就可以了) 再进入cust文件夹然后f---/cn/app 在这个文件夹里长按你要删除的定制软件 出来有个删 ...

  2. 2014-07-31 ASP.NET的母版页使用

    今天是在吾索实习的第17天.我在这天主要负责系统的骨架的搭建.首当其冲,要用的知识点就是ASP.NET母版页的使用了. ASP.NET的母版页有两种:一种是MasterPage,最常用也是最普通的母版 ...

  3. 读<<如何阅读一本书>>乱七八糟的笔记1

    阅读层次 第一层:基础阅读 第二层:检视阅读 系统化略读 第三层:分析阅读 第四层:主题阅读(比较阅读) 第二层:检视阅读 1.有系统的粗读或略读 (1)先看书名页,然后如果有序就先看序 (2)研究目 ...

  4. js原型继承深入

    js采用原型继承来实现类的派生,但是原型链再深入点,我们又知道多少呢,现在不妨往下看: 先来一个原型继承: var M1 = function() { this.param = "m1's ...

  5. HDU-2571命运

    Problem Description 穿过幽谷意味着离大魔王lemon已经无限接近了!可谁能想到,yifenfei在斩杀了一些虾兵蟹将后,却再次面临命运大迷宫的考验,这是魔王lemon设下的又一个机 ...

  6. HDU-2059龟兔赛跑(基础方程DP-遍历之前的所有状态)

    Problem Description 据说在很久很久以前,可怜的兔子经历了人生中最大的打击——赛跑输给乌龟后,心中郁闷,发誓要报仇雪恨,于是躲进了杭州下沙某农业园卧薪尝胆潜心修炼,终于练成了绝技,能 ...

  7. HDOJ 1248

    完全背包. 模版. 物品的价值等价于体积. #include <stdio.h> #include <string.h> using namespace std; int ma ...

  8. Highcharts教程2

    参数配置(属性+事件) chart.events.addSeries:添加数列到图表中. chart.events.click:整个图表的绘图区上所发生的点击事件. chart.events.load ...

  9. 关于javax.crypto.BadPaddingException: Blocktype错误的几种解决方法

    此文章转载自:http://www.myexception.cn/mobile/1259076.html 关于javax.crypto.BadPaddingException: Blocktype异常 ...

  10. iOS中block实现的探究

    [0. Brief introduction of block] Block是iOS4.0+ 和Mac OS X 10.6+ 引进的对C语言的扩展,用来实现匿名函数的特性. 用维基百科的话来说,Blo ...