• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            最近工作中遇到Window Ghosting這個問題, 感覺挺有意思,這里簡單記錄下。



            在XP時代我們的程序沒有響應后只能通過任務管理器強制殺掉,但是Vista之后情況變了, 我們?nèi)匀豢梢酝蟿邮ロ憫拇翱冢踔量梢試L試最小化和關閉窗口, 我們把這個特性叫住Window Ghosting。

            首先我們考慮下怎樣判斷一個窗口是否已經(jīng)失去響應?
             
            一般我們想到的是SendMessageTimeout,給窗口發(fā)送WM_NULL消息,判斷返回是否超時。這當然也是一種方法,但是系統(tǒng)有更方便的API  IsHungAppWindow, 該API是判斷窗口是否失去響應的標準方法。我們猜測IsHungAppWindow內(nèi)部是否通過SendMessageTimeout來實現(xiàn)的, 跟蹤下我們會發(fā)現(xiàn)不是我們想象的那樣, IsHungAppWindow內(nèi)部掉用了未公開的API NtUserQueryWindow。

            接下來考慮下 IsHungAppWindow 是如何鑒定一個窗口是否在失去響應狀態(tài)?

            這是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.
            簡單來說就是程序在非等待輸入狀態(tài) ,不是在程序啟動階段, 并且5秒內(nèi)沒有從消息隊列中取消息。 

            下面我們思考系統(tǒng)是如何實現(xiàn)Window Ghosting的?

            我們知道失去響應的窗口一般來說是因為UI線程正在做一些繁忙的工作, 或是UI線程死鎖而沒有在繼續(xù)運行了。 那這里就很奇怪了, UI線程都失去響應了, 窗口怎么還能響應我們的鼠標拖動消息?我們的鼠標拖動事件需要運行在UI線程中才行 ,該實現(xiàn)有些顛覆我們現(xiàn)有的計算機知識。

            這里的關鍵就是我們看到的失去響應的窗口是不是還是我們原來的窗口? 實際上我們真正的窗口已經(jīng)讓系統(tǒng)用Ghosting窗口替代了。
            完整過程是這樣的, 當系統(tǒng)檢測到我們程序窗口失去響應了, 系統(tǒng)進程(dwm.exe)會以相同的Z-order, 位置,大小和Style創(chuàng)建一個ghosting窗口(可以通過SPY查看 ,類名是Ghost), 我 們看到的失去響應的窗口就是這個窗口, 該窗口的客戶區(qū)內(nèi)容是從老窗口中拷貝過來的。而我們原來真正窗口依舊在那里(style, 位置,大小和z-order都沒有變 ), 但是dwm.exe合成屏幕內(nèi)容是并不會把這個窗口畫出來, 所以我們看起來就是原來的窗口給hide了。
             
            這就是Window Ghosting的奧秘, 我們可以在程序中調(diào)用 API DisableProcessWindowsGhosting 來禁止系統(tǒng)對我們的程序使用 Window Ghosting.

            Window Ghosting這個特性很不錯, 讓失去響應的程序也有很好的用戶體驗, 但是它也帶來了一些問題。

            我遇到的問題是我們在枚舉窗口的過程中,我們通過GetWindowRect查詢一個失去響應的程序窗口的位置,但是返回結(jié)果卻和我們屏幕上看到的不一致, 因為我們看到的是被我們拖動過的Ghosting window,但是API返回的確是被hide的原窗口的位置。 這種情況下我們需要原窗口和Ghosting窗口的一張映射表, 但是我還沒有找到他們對應關系的方法, 不知道系統(tǒng)又沒有相關API提供?一種方法是通過查找類名是"Ghost"的窗口,判斷進程是不是dwm.exe, 再通過標題匹配。但是該方法效率低,也不可靠。
            posted on 2014-01-08 21:26 Richard Wei 閱讀(3231) 評論(3)  編輯 收藏 引用 所屬分類: windows desktop

            FeedBack:
            # re: Window Ghosting
            2014-01-08 21:50 | relax
            挺有意思  回復  更多評論
              
            # re: Window Ghosting[未登錄]
            2014-01-08 22:12 | 萬連文
            記憶中是Send/PostMessage返回FALSE表示窗口假死,Chromium源碼中有的。Ghosting是很早就知道了,感覺有遮罩層的意思,方便接管消息做統(tǒng)一的假死處理。  回復  更多評論
              
            # re: Window Ghosting
            2014-01-09 10:24 | Richard Wei
            @萬連文
            對假死窗口調(diào)用SendMessage應該會一直等待,不會返回, 直到窗口有響應  回復  更多評論
              
            久久99精品国产麻豆蜜芽| 色8激情欧美成人久久综合电| 久久婷婷成人综合色综合| 国产69精品久久久久777| 国内精品伊人久久久久影院对白| 亚洲精品97久久中文字幕无码| 人妻丰满AV无码久久不卡| 国产精品九九久久精品女同亚洲欧美日韩综合区 | 久久水蜜桃亚洲av无码精品麻豆 | 国产精品日韩欧美久久综合| 深夜久久AAAAA级毛片免费看| 久久精品亚洲日本波多野结衣| 品成人欧美大片久久国产欧美| 狠狠色狠狠色综合久久| 国产精品一区二区久久精品| 色妞色综合久久夜夜| 99久久精品免费观看国产| 亚洲午夜久久久久久久久电影网 | 久久丫精品国产亚洲av| 久久天天日天天操综合伊人av| 狠狠88综合久久久久综合网| 久久无码AV中文出轨人妻| 精品久久一区二区三区| 国内精品久久久久影院薰衣草| 国产亚洲色婷婷久久99精品91| 精品综合久久久久久888蜜芽| 久久这里的只有是精品23| 精品欧美一区二区三区久久久| 狠狠久久亚洲欧美专区| 久久久免费精品re6| 国产69精品久久久久9999APGF| 天天综合久久一二三区| 国产亚洲成人久久| 久久99久久成人免费播放| 久久99毛片免费观看不卡| …久久精品99久久香蕉国产| 国产亚洲精品久久久久秋霞| 18禁黄久久久AAA片| 久久精品国产久精国产一老狼| 久久国内免费视频| 久久精品国产免费观看三人同眠|