老话题:自己编写只截窗口客户区的截屏软件(VB2010)

现在能实现截屏的软件很多,就不一一列举了,连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函数的申明都来在下面的网站,网站非常强大

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

时间: 2024-07-31 02:09:18

老话题:自己编写只截窗口客户区的截屏软件(VB2010)的相关文章

编程-想在窗口客户区上画很多条直线,该怎么做?

问题描述 想在窗口客户区上画很多条直线,该怎么做? 当我画完一条线后准备要画下一条线时,这条线消失了,有没有什么办法把刚画完的直线留下来,我想在这窗口上画很多条直线,如何修改代码才能实现? 解决方案 那个InvalidateRect()函数,最后一个参数写NULL就好了. 解决方案二: 弄一个数据结构,譬如数组,把每次画线的坐标存储起来,然后在PAINT中需要绘画的是每根直线

修改窗体非客户区大小更改窗体标题栏高度

想修改窗体的非客户区,首先就得明白为什么要修改非客户区,什么是非客户区 从窗体或控件来看,非客户区就是无法放置控件的区域,比如窗体的标题栏,和边框,菜单栏也是非客户区,菜单栏不是控件是画上去的 文本框的边框,滚动条区域都是非客户区 为什么要修改非客户区呢?? 原因是为了自绘,让边框好看一些,比如要加高窗体标题栏,就需要改非客户区,自绘非客户区会响应 WM_NCPAINT消息 在这个消息里,你可以进行窗体,控件,非客户区的自绘 好啦,现在转入正题,要修改非客户大小,必须处理 WM_NCCALCSI

vBulletin HACK----显示话题大小和打开新窗口于论坛索引页

vBulletin HACK ----显示话题大小和打开新窗口于论坛索引页 作者:gogosoft <显示话题大小> 原因:1.1.4版本中没有此功能,而部分用户会以此作为是否查看话题的参考因素. 优点:只需要增加几行代码就可以. 缺点:因为每次显示论坛索引页都需要对该页的话题全部计算大小,所以可能会对服务器造成若干的影响. 自评:这是一个小功能,可有可无,实用与否见仁见智. 步骤: ⒈打开 forumdisplay.php ,查找" if ($announcement=$DB_si

datagridview-用VS编写的C#窗口程序的dataGridview里的滚动条不动QAQ

问题描述 用VS编写的C#窗口程序的dataGridview里的滚动条不动QAQ 求助!卤煮有个VS编写的C#窗口程序,窗体内大概有几个选项卡,其中一个选项卡里有三个分区,最上面的都是按钮,不提.下面两个分区分别有两个数据列表,可以点击按钮以后加载入某个数据库的数据,一条一条显示. 然后问题就出现了,右边的dataGridview控件里的列表没什么问题,超出窗口高度了就自动产生了滚动条,可以滚动浏览. 左边的dataGridview控件里的列表在加载列表的时候也会产生滚动条,但是等全都加载完以后

vBulletin HACK----显示话题大小和打开新窗口于论坛索引页_php基础

vBulletin HACK ----显示话题大小和打开新窗口于论坛索引页 作者:gogosoft <显示话题大小> 原因:1.1.4版本中没有此功能,而部分用户会以此作为是否查看话题的参考因素. 优点:只需要增加几行代码就可以. 缺点:因为每次显示论坛索引页都需要对该页的话题全部计算大小,所以可能会对服务器造成若干的影响. 自评:这是一个小功能,可有可无,实用与否见仁见智. 步骤: ⒈打开 forumdisplay.php ,查找" if ($announcement=$DB_si

插件开发-Qt Creator 用插件法编写一个自定义窗口部件

问题描述 Qt Creator 用插件法编写一个自定义窗口部件 系统自身条件: (1)我的系统是linux,Qt Creator 5.0.2. (2)我是用Qt Creator自带的帮助文档中的例子(analogclock). 按照说明一步一步做,构建通过,并且生成3个makefile文件,一个libanalogclockplugin.so文件,貌似这就是插件,我把它拷贝到Qt Creator中designer的插件目录下.本应该在Qt Creator重启后,可以在designer中可以看到这个

directx9 0-跪求DirectX全屏(无窗口)游戏的截屏代码

问题描述 跪求DirectX全屏(无窗口)游戏的截屏代码 跪求DirectX全屏(无窗口)游戏的截屏代码,dx9和dx11的都行,C++和C#的都行,不需要其它功能,只要能截下全屏的图就行!迫切! 解决方案 窗口全屏代码

mfc-MFC怎么将客户区变成非客户区

问题描述 MFC怎么将客户区变成非客户区 我用BCG库的停靠窗口在顶部创建了一个窗口,然后隐藏了原来的标题栏,菜单和工具栏,然后我想让在顶部的那个停靠窗口成为新的标题栏形势的非客户区,请问该怎么做,OnNCHitTest改写没用 解决方案 请详细描述你的问题呢.... 解决方案二: 你创建的是什么窗口?CDockablePane?

再谈客户区对话框拖动操作

<无标题对话框的拖动>,示范了如何用鼠标点击窗口或对话框背景(即客户区)进行拖动操作,文章中提供的解决方法在没有上下文菜单的情况下运行很正常,一旦有上下文菜单时,文中所提供的方法便显现出了缺陷--上下文菜单无法显示出来.本文将针对这个问题对前一篇提出的方法进行改进. 当初实现拖动的基本思路是改写 OnNcHitTest 例程,让鼠标在客户区中的点击始终返回 HTCAPTION 而不是 HTCLIENT,从而诱使 Windows 实现拖动操作.没想到这样做使上下文菜单的操作出现了混乱,原因是如果