Windows桌面共享中一些常見的抓屏技術

2021-08-07 11:21:33 字數 3436 閱讀 3475

windows桌面共享中一些常見的抓屏技術

1. bitblt

我想做windows開發應該都知道這個api, 它能實現dc間的內容拷貝, 如果我們把源dc指定成monitor dc或是桌面dc, 它就能實現抓屏功能。

a. 在xp下我們可以通過最後的拷貝標誌來控制是否拷貝layered window, 只有srccpy表示拷貝內容不包含layered window, 如果是srccpy | captureblt表示拷貝包括layered window在內的所有視窗。 這個標誌在vista之後的系統(win7/win8),開啟dwm的情況下, 已經失效, 因為這種情況下所有的視窗都是layered window.
b. 這種方式的抓屏在 vista之後, 開啟dwm的情況下, 抓屏速度非常慢(30ms +), 具體原因不知道是因為系統沒有快取整個螢幕的資料還是gpu向記憶體拷貝資料太慢了, 有知道的朋友可以提示下。

2. mirror driver

這種方法應該是win8之前最高效的抓屏方法, 也是微軟推薦的遠端桌面共享方案,它通過建立虛擬映象驅動, 直接獲取最終螢幕變化資料。

該方法也有一些缺點:

a. 涉及到驅動安裝, 技術難度大, 系統許可權要求也高

b. win8 上該方案已經失效, 但是還是有方法的, 參見 remote display drivers

3. gdi hook

這種方法應該說是xp時代比較流行的抓屏方法, 因為所有的繪製都是通過gdi32.dll中的繪圖函式來實現的, 所以我們只要攔截了這些函式, 系統的所有繪製就都讓我們控制了。這種方法應該來說也是一種挺高效的抓屏方法,螢幕的變化也都能讓我們攔截到, 同時因為好多繪圖函式是以向量方式實現的,所有抓到的資料報非常小, 即使在低頻寬下也效果挺好。

下面是該方法的一些缺點:

a. hook技術本身就有其複雜性和不穩定性, 尤其是hook所有程序
b. vista只有越來越多程式採用d2d/d3d繪製, gdi hook對這些繪製無能為力。
c. vista之後uac開啟的情況下, 如果我們的程式許可權不夠高, hook不到更高許可權的程式。

4. windows media api

windows media 9.0 支援用windows media encoder 9 api來抓屏。它有乙個編碼器叫windows media video 9 screen codec,特別為抓屏優化過。windows media encoder api提供了乙個iwmencoder2介面可以用來高效地捕捉螢幕影象。

因為對這組api不熟, 這種抓屏方法我也沒嘗試過, 具體可見

various methods for capturing the screen

, 感覺這種方法的最大缺點是使用者機器需要安裝

windows media encoder 9。

5. directx

每個directx程式都包含乙個被我們稱作緩衝的記憶體區域,其中儲存了和該程式有關的視訊記憶體內容,這在程式中被稱作後台緩衝(back buffer),有些程式有不止乙個的後台緩衝。還有乙個緩衝,在預設情況下每個程式都可以訪問-前台緩衝。前台緩衝儲存了和桌面相關的視訊記憶體內容,實質上就是螢幕影象。 我們的程式通過訪問前台緩衝就可以捕捉到當前螢幕的內容。上面的列子中也包含該方法的實現, 是基於directx9的,我們可以參考下, 據我測試該方法在dwm開啟的情況下抓整屏也要30ms左右。vista之後的directx 10/11相對於directx 9 已經發生非常大的變化, 直接用新的介面上面的**未必能正常工作。

6. printwindow

該方法本身不能直接做為一種抓屏方法, 但是有時候我們要獲取某個視窗的內容, 即使他被其他視窗覆蓋著, 這時候這個函式就很有用。該方該呼叫法的原理是通過給目標視窗傳送wm_print或是wm_printclient訊息, 所以如果目標視窗沒有響應, 該呼叫可能會阻塞抓屏執行緒, 這種情況下抓屏前最好先用sendmessagetimeout檢測目標視窗是否有響應。另外該方法也抓不到d3d視窗的內容。

7. dwm/dxgi hook

vista之後微軟放棄了xp時代的xpdm, 採用了全新的wddm視屏驅動模型, 現在win8.1上已經是wddm1.3.

vista之後底層所有的渲染都是基於d3d技術, 另外我們也知道系統在dwm.exe裡進行視窗邊框的繪畫和合成, 所以理論上我們可以通過hook dwm/d3d/dxgi,攔截到整個系統的螢幕內容。當然作為一種hook技術, 它也有上面gdi hook類似的問題。

8. magnification

這組api是微軟vista之後開放給我們開發放大鏡程式的, 它裡面提供了乙個api讓我們攔截到顯示的內容, 可惜的是這個關鍵的api  magsetimagescalingcallback 微軟已經宣布作廢。另外該方式的抓屏效率也不高, 整屏需要60 ms 左右。

9. desktop duplication

這是微軟win8 上宣布放棄mirror driver之後推薦採用的抓屏技術, 全部基於d3d/dxgi技術, 效率非常高, 並且包含變化區域和螢幕滑鼠游標。它的缺點是沒法抓取某個視窗的內容 。

10. getwindowdc

該方法和printwindow類似,但是它沒有printwindow的許可權問題, 也沒有超時問題。

它的主要問題是有些視窗抓到的內容不包含非客戶區,有些視窗比如工作列的thumbnail視窗會抓不到內容。

最後簡單總結下 , 我們可以看到windows系統上基本沒有一種通用的抓屏技術可以高效的抓取所有的系統(xp/win7/win8), 很大一部原因是作業系統的顯示驅動模型在從xpdm向wddm轉變, 應用層的api也在從gdi向d3d轉變 。 相對於linux的穩定, window的不斷發展和進步, 對開發人員究竟是喜是悲?

Windows桌面共享中一些常見的抓屏技術

轉至 1.bitblt 我想做windows開發應該都知道這個api,它能實現dc間的內容拷貝,如果我們把源dc指定成monitor dc或是桌面dc,它就能實現抓屏功能。a.在xp下我們可以通過最後的拷貝標誌來控制是否拷貝layered window,只有srccpy表示拷貝內容不包含layere...

Windows桌面共享中一些常見的抓屏技術

1.bitblt 我想做windows開發應該都知道這個api,它能實現dc間的內容拷貝,如果我們把源dc指定成monitor dc或是桌面dc,它就能實現抓屏功能。a.在xp下我們可以通過最後的拷貝標誌來控制是否拷貝layered window,只有srccpy表示拷貝內容不包含layered w...

Windows桌面共享中一些常見的抓屏技術

1.bitblt 我想做windows開發應該都知道這個api,它能實現dc間的內容拷貝,如果我們把源dc指定成monitor dc或是桌面dc,它就能實現抓屏功能。a.在xp下我們可以通過最後的拷貝標誌來控制是否拷貝layered window,只有srccpy表示拷貝內容不包含layered w...