老話題:自己編寫只截窗口客戶區的截屏軟件(VB2010)


現在能實現截屏的軟件很多,就不一一列舉了,連WIN7都自帶截屏軟件,甚至OFFICE2010開始都有截屏的功能。

 

截屏軟件雖多,無外乎三種截屏方式:全屏截圖、窗口截圖、自定義矩形截圖。

 

其中,窗口截圖用的比較多,下面就是一個窗口截圖的示例:

image

 

但有時我們僅僅希望截取窗口的客戶區,如下圖所示:

image

 

這樣的軟件並不多,折中的辦法是用自定義矩形截圖,但是要調整矩形並不是一件很容易的事。

 

於是,基於碼農的精神,自給自足。

於是上網搜了搜解決方案。有兩個

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函數的申明都來在下面的網站,網站非常強大

http://www.pinvoke.net/index.aspx


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM