最近工作 中有個(gè)需求是抓取桌面截圖, 這里的桌面是指點(diǎn)了“顯示桌面”之后看到的桌面, 截圖內(nèi)容包括桌面背景和圖標(biāo)以及任務(wù)欄,如下圖:
注意需求是:即使當(dāng)前其他窗口蓋在我們的桌面上,我們要求抓取到的內(nèi)容也是這些窗口背后的桌面。
思考怎么樣才能在程序運(yùn)行時(shí),動(dòng)態(tài)抓取該截圖?
大概想了些方法:
(1) 通過Desktop DC, 然后BitBlt
點(diǎn)評(píng): 通過這種方法抓取到的截圖是當(dāng)前桌面的所有窗口,包括其他當(dāng)前打開顯示的窗口 , 這不是我們所期望的。
另外我們也不可能在需要截圖時(shí)最小化所有窗口, 截完了再還原。
(2)通過注冊(cè)表獲取桌面壁紙保存的地方
點(diǎn)評(píng):獲取到該壁紙, 沒有圖標(biāo)和任務(wù)欄, 也不是我們所期望的。
(3)通過DWM特性來獲取
點(diǎn)評(píng): Vista后的Desktop Window Manager(DWM)特性,可以讓我們通過DwmRegisterThumbnail,DwmUpdateThumbnailProperties等API實(shí)時(shí)顯示某個(gè)窗口的截圖。可惜獲取到的內(nèi)容只能顯示在我們預(yù)定義的窗口里, 但是我們沒法獲取里面的內(nèi)容。另外這個(gè)特性只有Vista之后才支持, XP系統(tǒng)怎么辦?
(4)通過Magnification來獲取
點(diǎn)評(píng):我們可以通過系統(tǒng)的放大鏡技術(shù),過濾掉蓋在桌面上的其他窗口(MagSetWindowFilterList),然后通過MagSetImageScalingCallback攔截內(nèi)容。該技術(shù)的問題一是過濾窗口的個(gè)數(shù)限制, 另外也只能適用于Vista之后。
(5)通過API Hook技術(shù)
點(diǎn)評(píng):通過API Hook技術(shù)我們可以動(dòng)態(tài)攔截桌面窗口DC的繪畫動(dòng)作,這樣就可以攔截或是合成窗口內(nèi)容了。但是一來這樣做比較復(fù)雜, 穩(wěn)定性也很難保證,另外也有殺雞用牛刀的感覺。
(6)通過PrintWindow技術(shù)
點(diǎn)評(píng):PrintWindow API內(nèi)部通過WM_PRINTCLIENT和WM_PRINT來獲取窗口截圖, 這個(gè)API在XP時(shí)代工作的不是很好,但是在Vista之后已經(jīng)比較穩(wěn)定了。
我們最后選擇通過PrintWindow API來獲取桌面截圖, 大概過程如下:
a. 獲取桌面窗口(Program Manager)的內(nèi)容
b. 獲取TaskBar窗口的位置和內(nèi)容
c. 把TaskBar窗口內(nèi)容和桌面內(nèi)容合成, 貼在正確的位置
這里說一下要注意的一些問題:
a . 注意窗口的層次
Aero模式下, Program Manager窗口只包含背景圖片, 圖標(biāo)列表在WorkerW窗口下:
Basic模式下窗口內(nèi)容都在Program Manager窗口下:
b. 注意多顯示器的情況, 多顯示器時(shí)除了主顯示器,其他顯示器桌面是沒有任務(wù)欄的
c. 注意任務(wù)欄的位置, 任務(wù)欄是可以Dock到任何地方并且可以隱藏的,不要hard code在下面了。
d. XP下對(duì)ProgramManager窗口調(diào)用PrintWindow會(huì)有刷新問題。一直沒有好的解決方案, 所以對(duì)XP勉強(qiáng)采用第一種DC的方式了。
因此, 我到現(xiàn)在還沒有找到完整解決我們這個(gè)問題的方法, 不知道大家有沒有好的思路?
posted on 2013-08-30 20:30
Richard Wei 閱讀(7987)
評(píng)論(2) 編輯 收藏 引用 所屬分類:
windows desktop