現在能實現截屏的軟件很多,就不一一列舉了,連WIN7都自帶截屏軟件,甚至OFFICE2010開始都有截屏的功能。
截屏軟件雖多,無外乎三種截屏方式:全屏截圖、窗口截圖、自定義矩形截圖。
其中,窗口截圖用的比較多,下面就是一個窗口截圖的示例:
但有時我們僅僅希望截取窗口的客戶區,如下圖所示:
這樣的軟件並不多,折中的辦法是用自定義矩形截圖,但是要調整矩形並不是一件很容易的事。
於是,基於碼農的精神,自給自足。
於是上網搜了搜解決方案。有兩個
1、基於Win API函數的PrintWindow函數
2、基於Graphics對象的CopyFromScreen方法
兩種方法各有優缺點
PrintWindow函數是把指定Hwnd的窗口的內容繪制到指定的Hdc中,基於后台完成。甚至指定的窗口最小化時,也能把窗口正常時的內容繪制到Hdc中。估計原理是,發出一個繪制命令,系統便繪制了窗口內容。不過,這個方法有很大的局限性,若窗口內容中有用DirectX等非GDI方法時,截取的圖像是一片黑。
CopyFromScreen方法實際上是把屏幕上的內容截取到Bitmap對象。優點是經過系統優化,可以截取含有DirectX等非GDI方法的內容。缺點是由於截取的是屏幕,故指定的窗口不能最小化,還需要自己計算要截取的范圍。
由於要截取含有DirectX等非GDI方法的內容。故本文采用的是CopyFromScreen方法。
問題就是如何計算指定窗口的客服區的范圍。
需要利用如下的Win API函數:
FindWindowByCaption:根據指定的標題文本找尋窗口,返回窗口的句柄Hwnd
GetWindowRect:獲得指定Hwnd的窗口的區域,返回True表示獲得成功,在參數lpRect里獲得窗口的區域。
GetClientRect:獲得指定Hwnd的窗口的客戶區區域,返回非0表示成功,在參數lpRect里獲得窗口的客戶區的區域。但是該區域的X和Y分量都是0,也就是只能獲得該區域的寬和高,而不能獲得該區域在屏幕上的位置。
ClientToScreen:把客戶區的坐標轉換為屏幕坐標。該函數配合GetClientRect函數可以獲得窗口的客戶區區域(包括X和Y分量,即該區域在屏幕上的位置)
具體的獲得窗口的客戶區的區域的過程如下:
1、用GetClientRect獲得窗口的客戶區區域
2、用ClientToScreen函數獲得客戶區的(0,0)坐標在屏幕上的坐標,也是客戶區在屏幕上的偏移位置。
3、把偏移量添加到步驟1中的區域,那就是獲得完整的客戶區區域(包括X和Y分量,即該區域在屏幕上的位置)
再引入兩個輔助Win API函數:
OpenIcon:把指定Hwnd的窗口還原為正常(也就是把最小化的窗口還原成正常窗口)
BringWindowToTop:把指定Hwnd的窗口顯示在頂部,不被其他窗口覆蓋
Public Shared Function SnapWindowByCaption(Caption As String, Optional OnlyClient As Boolean = False, Optional AutoRestore As Boolean = False, Optional AutoBringToTop As Boolean = False) As Bitmap
Dim Hwnd As IntPtr = FindWindowByCaption(0, Caption)
If Hwnd = 0 Then Return Nothing
Dim R As New RECT(0, 0, 0, 0)
GetWindowRect(Hwnd, R)
If R.Width = 0 Then
If AutoRestore = True Then
OpenIcon(Hwnd)
GetWindowRect(Hwnd, R)
Else
Return Nothing
End If
End If
If AutoBringToTop = True Then BringWindowToTop(Hwnd)
Dim P As New WinPOINT(0, 0)
If OnlyClient = True Then
GetClientRect(Hwnd, R)
ClientToScreen(Hwnd, P)
R.X += P.X
R.Y += P.Y
End If
Dim w As Integer = R.Width
Dim h As Integer = R.Height
Dim bmp As Bitmap = New Bitmap(w, h)
Dim g As Graphics = Graphics.FromImage(bmp)
g.CopyFromScreen(R.X, R.Y, 0, 0, New Size(w, h))
Return bmp
End Function
最后說點題外話,本文中的Win API函數的申明都來在下面的網站,網站非常強大