已阅读5页,还剩5页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
屏幕截图软件设计杨金(西北农林科技大学信息工程学学院计算机科学与技术2002级3班 陕西杨凌 712100 )摘要: 本文阐述 vc+实现屏幕截图功能的原理和具体设计步骤,所实现的这个抓图软件可以截取整个屏幕,截取指定的窗口,并将截取到的图像以bmp文件形式保存到指定的路径下。技术重点在鼠标在屏幕上的准确定位;如何获取抓图的窗口句柄;如何对抓到的图片进行保存的问题。技术难点在如何将所抓取的屏幕窗口保存为磁盘bmp文件形式。关键词:屏幕截图;bmp位图;设备环境(dc)1 引言在我们的日常上网活动当中比如看电影、玩游戏、做图等等会对一些画面特别喜欢!但是却没有办法将这些画面以图片形式保存下来,真是犹如“水中月,镜中花”看得到却得不到。由于qq的出现,曾改变了几亿人的交流生活方式,它的里面嵌入的任意截图功能,更是为人们的生活增添了无限的欢愉和快乐,通过截图自己可以将最喜欢的游戏画面,最喜欢的电影画面,以图片形式保存,可以及时的发给好友共享,给我们带来了意想不到的帮助和惊喜。另外系统的功能强大的截图软件在社会建设的各个领域都到了施展空间,为人们的工作生活创造了极大的方便,解决了许多棘手难题。可以说呀抓图软件有很广阔的应用前景,虽然它不算是很庞大的系统软件,但是其它的大型的主流系统软件能够嵌入抓图的功能,必将受到极大的欢迎和青睐。所以在此次软件课程设计当中,我选择了用vc制作屏幕截图的软件,实现截取指定窗口,整个屏幕的功能,并且将截取的图形以bmp文件形式存放在指定路径的磁盘当中。本文将系统介绍截图软件的设计原理,设计步骤,设计方法,和运用的重点技术。2 实现基本原理和运用相关技术抓图软件基本原理就是把屏幕上所抓取的图像复制到内存中,并最后将内存中的图像内容以位图文件形式保存到磁盘当中。在这此软件设计当中,如果用户将鼠标左键按住不放,则开始抓取图片,此时隐藏程序窗口,以免影响在抓取时的“视野”,接着装入“魔法棒”鼠标,开始追踪鼠标的移动,然后获得鼠标所在处的窗口句柄,取得屏幕的设备环境句柄,以便在屏幕的任何位置绘图。接下来建立一红色的画笔,得到鼠标所在处的窗口的区域,在鼠标所在处的窗口四周画一红色的矩形,做为选定时的提醒。当鼠标左键释放的时候得到鼠标所在处的窗口的区域宽、高,然后建立一个屏幕设备环境句柄和与屏幕设备环境句柄兼容、与鼠标所在处的窗口的区域等大的位图,把新位图选到内存设备描述表中,最后把屏幕设备描述表拷贝到内存设备描述表中,终止鼠标捕获,恢复窗口显示模式。那么最后要作的工作就是写一个位图保存函数将内存当中的窗口图片信息以位图形式保存到指定磁盘当中。在整个程序当中要用到大量的函数:比如申请内存空间用于存放位图文件 globalalloc(ghnd,filelength); 位图文件读入所申请内存空间中loadfiletomemory( mpbitssrc,mfilename); 在onpaint等函数中用创建显示用位图;用createdibitmap()创建显示用位图;用createcompatibledc()创建兼容dc, 用selectbitmap()选择显示位图; 用bitblt或stretchblt等函数显示位图 ; 用deleteobject()删除所创建的位图;程序中还会用到许多关键函数在这里不在详细叙述,其功能用法可以参照msdn。屏幕抓图程序的关键有两点:一是应该知道鼠标在屏幕上有准确位置;二是应该知道欲抓图的窗口句柄;三是如何对抓到的图片进行保存的问题。对于问题一,很简单,利用setcapture函数便能够追踪鼠标的移动(包括在屏幕抓图程序窗口之外的窗口)。对于问题二,这时会用到一个平时我们不常用的函数:windowfrompoint,其函数用法如下:hwnd windowfrompoint point point; /坐标;这个函数能够找出鼠标当前位置所对应的窗口句柄。具体用法可以参见msdn,这里不做详细叙述。在选择抓图窗口时,鼠标的在位置的窗口都会出现加粗的有色边框,以提醒目前所选择的窗口,这个功能实现起来有些复杂,它的代码如下:point pt5; pt0 = cpoint(rectcapture.left, rectcapture.top); pt1 = cpoint(rectcapture.right,rectcapture.top); pt2 = cpoint(rectcapture.right,rectcapture.bottom); pt3 = cpoint(rectcapture.left, rectcapture.bottom); pt4 = cpoint(rectcapture.left, rectcapture.top);在gdi中,最常见的一个概念就设备环境(dc),每一个窗口都相应的具有自己的dc。如果能够调用到窗口的dc,那么,我们便能够在窗口上的任何位置绘图。然而,在屏幕抓图程序中,由于用户所选择的窗口是不固定的,所以,要想得到鼠标所在处的窗口的dc,不是很容易。但是能够随心所欲地在屏幕上进行绘图却又不仅限于特定的窗口,getdc能够做到这点! getdc的函数申明:hdc getdc( hwnd hwnd),hwnd是dc对应的窗口句柄,当hwnd为空时,该函数返回的是整个屏幕的设备环境句柄!这就意味着我们可以在屏幕上进行任意绘图。在鼠标所在处的窗口进行绘图时,绘图本身的目的只是为了提醒用户目前所选择的窗口,所以,在进行绘图时,必须得保证不会破坏窗口原有的画面。这点很好办,将窗口的dc绘图模式设为r2_notxorpen(将画笔颜色与屏幕颜色进行异或后,再将屏幕颜取反),这样,在同一个地方进行两次绘图后(对同一像素进行两次异或运算,像素值并不会发生变化),窗口的画面并不会发生任何变化。以上就是此次截图软件设计当中运用的相关技术和设计实现原理。3 软件详细设计31建立基于对话框的工程文件启动visual c+,生成一个基于对话框的工程,工程名为“capture”. 然后准备好一个外形为细长矩形的光标文件(*.cur),将之引入资源管理器(idc_camera)。接着在ccapturedlg类中加入两个全局变量:hwnd hwndcapture; crect rectcapture; uint nflags;cpoint point;lpctstr lpfilename;hbitmap hbitmap;32添加消息响应函数然后通过类向导加入对wm_mousemove及wm_lbuttonup事件的响应函数,添加wm_mousemove事件的响应函数代码该函数主要实现的功能:鼠标左键按住不放,则开始抓取图片,此时隐藏程序窗口,以免影响在抓取时的“视野”,接着装入“魔法棒”鼠标,开始追踪鼠标的移动,然后获得鼠标所在处的窗口句柄,取得屏幕的设备环境句柄,以便在屏幕的任何位置绘图。接下来建立一红色的画笔,得到鼠标所在处的窗口的区域,在鼠标所在处的窗口四周画一红色的矩形,做为选定时的提醒。void ccapturedlg:onmousemove(uint nflags, cpoint point) /如果用户将鼠标左键按住不放,则开始抓取图片 if(nflags=mk_lbutton) /隐藏程序窗口,以免影响在抓取时的“视野” showwindow(sw_hide); /装入“魔法棒”鼠标,开始追踪鼠标的移动 hcursor cur=loadcursor(afxgetinstancehandle(),makeintresource(idc_camera ); setcursor(cur); setcapture(); /获得鼠标所在处的窗口句柄 clienttoscreen(&point); hwndcapture=(hwnd):windowfrompoint(point); /取得屏幕的设备环境句柄,以便在屏幕的任何位置绘图 hdc hdc=:getdc(null); /建立一红色的画笔 hpen hpen =createpen(ps_insideframe,6, rgb(255,0,0); /将绘图模式设为r2_notxorpen,在绘图时可以不破坏原有的背景 int nmode =setrop2(hdc, r2_notxorpen); hpen hpenold= (hpen)selectobject(hdc, hpen); /得到鼠标所在处的窗口的区域 :getwindowrect(hwndcapture,&rectcapture); /在鼠标所在处的窗口四周画一红色的矩形,做为选定时的提醒 point pt5; pt0 = cpoint(rectcapture.left, rectcapture.top); pt1 = cpoint(rectcapture.right,rectcapture.top); pt2 = cpoint(rectcapture.right,rectcapture.bottom); pt3 = cpoint(rectcapture.left, rectcapture.bottom); pt4 = cpoint(rectcapture.left, rectcapture.top); :polyline(hdc,pt,5); /延时后再重绘红色的矩形,这样就不会破坏原有内容 sleep(100); :polyline(hdc,pt,5); :selectobject(hdc,hpenold); :releasedc(null,hdc); cdialog:onmousemove(nflags, point);添加wm_lbuttonup事件的响应函数代码:该函数主要实现当鼠标左键释放的时候得到鼠标所在处的窗口的区域宽、高,然后建立一个屏幕设备环境句柄和与屏幕设备环境句柄兼容、与鼠标所在处的窗口的区域等大的位图,把新位图选到内存设备描述表中,最后把屏幕设备描述表拷贝到内存设备描述表中,终止鼠标捕获,恢复窗口显示模式。void ccapturedlg:onlbuttonup(uint nflags, cpoint point) /得到鼠标所在处的窗口的区域宽、高 int nwidth=rectcapture.width(); int nheight=rectcapture.height(); hdc hdcscreen, hmemdc; hbitmap holdbitmap; /建立一个屏幕设备环境句柄 hdcscreen = createdc(display, null, null, null); hmemdc = createcompatibledc(hdcscreen); /建立一个与屏幕设备环境句柄兼容、与鼠标所在处的窗口的区域等大的位图 hbitmap = createcompatiblebitmap(hdcscreen, nwidth, nheight); / 把新位图选到内存设备描述表中 holdbitmap =(hbitmap)selectobject(hmemdc, hbitmap); / 把屏幕设备描述表拷贝到内存设备描述表中 bitblt(hmemdc,0,0,nwidth,nheight,hdcscreen,rectcapture.left,rectcapture.top,srccopy); /取回鼠标所在处的窗口屏幕位图的句柄 hbitmap =(hbitmap)selectobject(hmemdc, holdbitmap); deletedc(hdcscreen); deletedc(hmemdc); messagebox(屏幕内容已经剪切获得,请单击对话框菜单按纽保存为bmp文件!); /终止鼠标捕获 releasecapture(); /恢复窗口显示模式 showwindow(sw_normal); cdialog:onlbuttonup(nflags, point);33将抓取的窗口图片保存为位图文件存取设计保存函数savebitmaptofile(hbitmap hbitmap, lpctstr lpfilename),并且在前面对话框类里面进行函数声明。此函数是整个软件设计当中的技术难点,要特别对bmp位图文件非常熟悉,bmp文件由文件头、位图信息头、颜色信息和图形数据四部分组成。bmp文件头数据结构含有bmp文件的类型、文件大小和位图起始位置等信息。位图文件的类型,必须为bm位图文件的大小,以字节为单位,位图文件保留字,必须为0位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位。bmp位图信息头数据用于说明位图的尺寸等信息。在typedef struct tagbitmapinfoheader结构当中dword bisize表示本结构所占用字节数;longbiwidth表示位图的宽度;以像素为单位longbiheight表示位图的高度,以像素为单位word biplanes表示目标设备的级别,必须为1;word bibitcount表示每个像素所需的位数,必须是1(双色),4(16色),8(256色)或24(真彩色)之一;dword bicompression; 表示位图压缩类型,必须是 0(不压缩), 1(bi_rle8压缩类型)或2(bi_rle4压缩类型)之一,dword bisizeimage表示位图的大小,以字节为单位;longbixpelspermeter表示位图水平分辨率,每米像素数;longbiypelspermeter表示位图垂直分辨率,每米像素数;dword biclrused表示位图实际使用的颜色表中的颜色数;dword biclrimportant表示位图显示过程中重要的颜色数。颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个rgbquad类型的结构,定义一种颜色。rgbquad结构的定义如下: 在typedef struct tagrgbquad 中bytergbblue表示 蓝色的亮度(值范围为0-255);bytergbgreen表示绿色的亮度(值范围为0-255);bytergbred表示 红色的亮度(值范围为0-255);bytergbreserved表示 保留,必须为0。颜色表中rgbquad结构数据的个数有bibitcount来确定:当bibitcount=1,4,8时,分别有2,16,256个表项;当bibitcount=24时,没有颜色表项。位图信息头和颜色表组成位图信息,bitmapinfo结构定义如下:typedef struct tagbitmapinfo bitmapinfoheader bmiheader; / 位图信息头rgbquad bmicolors1; / 颜色表 bitmapinfo;位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数: 当bibitcount=1时,8个像素占1个字节;当bibitcount=4时,2个像素占1个字节;当bibitcount=8时,1个像素占1个字节;当bibitcount=24时,1个像素占3个字节;windows规定一个扫描行所占的字节数必须是 4的倍数(即以long为单位),不足的以0填充, 一个扫描行所占的字节数计算方法: datasizeperline= (biwidth* bibitcount+31)/8表示一个扫描行所占的字节数; datasizeperline= datasizeperline/4*4表示字节数必须是4的倍数 ,位图数据的大小(不压缩情况下):datasize= datasizeperline* biheight; 在savebitmaptofile()当中首先定义调色板大小,位图中像素字节大小 ,位图文件大小,写入文件字节数,位图属性结构,位图文件头结构,位图信息头结构,指向位图信息头结构定义文件,分配内存句柄,调色板句柄,计算位图文件每个像素所占字节数,计算调色板大小。计算调色板大小,设置位图信息头结构,为位图内容分配内存,处理调色板,恢复调色板,创建位图文件,设置位图文件头,写入位图文件头,写入位图文件其余内容,最后清除返回。这样此函数就实现了将内存中的屏幕图像数据保存为位图文件形式,它的具体实现代码限于篇幅在这里就不多做介绍了,如果要想详细查看此函数的编写代码,可以在程序文件当中查看。34软件界面设计和其它相关功能设计由于本软件是基于对话框的工程,其界面相对比较单一简单,那么为了使得界面比较漂亮美观,我特别进行了对话框的渐变色设计,使界面有梦幻般的感觉。对话框的渐变色效果是在onpaint()函数中实现的 ,具体实现细节在这里不多做描述了。在软件设计的最后收尾阶段,实现文件的退出菜单功能设计。图1是该抓图软件的运行界面图形。 (图1)35软件运行功能测试图启动工程执行程序,出现图1程序界面时,用鼠标按下左键,程序界面便隐藏,于是拖动鼠标开始屏幕抓图。当鼠标左键释放后,程序会弹出一个messagebox对话框来提醒您已经抓取了指定窗口的图片请单击对话框菜单按钮保存为指定磁盘路径的bmp文件,接下来程序窗口出现,最后点击菜单按钮保存抓取的窗口图片。图2就是抓取的全屏位图。 (图2)此抓图软件不仅仅可以抓取全屏图案,还可以抓取任意指定窗口的图形。图3是 抓取指定小窗口的bmp图片。(图3)当抓图结束后,可以单击界面上的菜单退出按钮安全退出,此时程序又会弹出一个messagebox对话框提醒您是否确定要退出程序。通过大量的调试和运行,该抓图软件运行稳定,抓取保存速度比较快,整体性能比较理想。完成了任意指定窗口的界面截取功能及保存功能。4 存在问题和改进意见在此次屏幕截图软件设计当中主要面对三个问题,一是如何知道鼠标在屏幕上的准确位置;二是如何知道欲抓图的窗口句柄;三是如何对抓到的图片进行保存的问题。对于问题一,很简单,利用setcapture函数便能够追踪鼠标的移动,包括在屏幕抓图程序窗口之外的窗口。应该注意的是,setcapture的具体功能并不像msdn中所说的那样:调用setcapture一次直到使用releasecapture终止鼠标捕获前都会起到对鼠标的捕获作用,实际上,在使用过程中,就会发现,在进行了一次鼠标捕获之后,setcapture便失去了作用,这可能是setcapture函数的一个bug。所以,在编程时,要不断地调用setcapture函数,以保证setcapture能够对鼠标进行正确无误的捕获。对于问题二,这时会用到一个平时我们不常用的函数:windowfrompoint,这个函数能够找出鼠标当前位置所对应的窗口句柄。问题最多当要属问题三:如何对抓到的图片进行保存且保存为指定位置的bmp文件,这个是整个程序设计当中的难点也是最麻烦的出了很多棘手的问题,由于需要设计一个这样的保存函数,限于自身水平就参考了网上同仁编写的这种功能的函数,于是拿到自己的程序中调用此函数便陷入了尴尬的境地,首先是出现了二三十处语法错误经过耐心修改全部搞定,但是执行程序,单击保存按钮却无法进行保存,一运行会发出错误报告然后自动退出,经过确定是程序逻辑错误,后经过调试是应为在写这个函数的时候,一个参数有问题,是因为该参数是在前面的一个函数中定义过且为私有变量,后面的函数需要调用这个参数,来获取屏幕位图窗口句柄,那么这个参数就需要设置为全局变量,在这里我就犯了这个低级错误。接着执行程序抓图保存,但是令人惊讶的是机子接近崩溃的边缘,运行比“蜗牛”还慢,等大约67分钟后,一切才恢复正常,最后到保存的指定文件中去查看所保存的抓取图片,让人吃惊的是保存的图片大小为655m,怪不得执行程序后会那么慢,经过分析问题出在,设置保存为bmp文件得时候,抓取窗口得长宽大小在函数savebitmaptofile()中并没有获得,那么程序运行得时候就任意设置了一个很大得窗口尺寸,才使得所保存得图片大得惊人。经过龙满生老师得细心指导和调试解决了这个问题。但是又有令人郁闷得问题出现了,拿就是所保存得图片大小合适是所抓取窗口的大小,但是图片一片漆黑!龙满生老师说肯定是因为所抓取的图片数据没有获得,用debug设置断点调试明显显示getdibits()的数据值为0,但是始终搞不清楚为什么所获得的位图数据值是零,龙满生老师细心的帮我分析,最后才确定出罪魁祸首是deletedc(hdc);该函数用错了位置,它在getdibits()函数调用之前便调用了那么当然获取的位图数据为零了,于是调整deletedc(hdc)为在getdibits()函数调用之后调用,终于解决了这个问题。那么到最后该软件就算大功告成了。 该软件特别要改经的地方那就是能够像qq抓图那样任意拖动鼠标,截取任意大小的图片,并且所见即所抓,不管它是什么东东,游戏画面也好,电影画面也好,flansh,静态图片等等,像怎么抓就怎么抓。但是限于自身能力有限还有时
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 教师师徒结对计划
- 《材料成型工艺基础A》教学大纲
- 玉溪师范学院《网球》2023-2024学年第一学期期末试卷
- 施工现场项目部管理制度
- 火山引擎·数据飞轮-行业实践系列自皮书·银行业 -新一代全行级标签体系与标签应用篇 2024
- 2024年细微射频同轴电缆项目评估分析报告
- 2023年有机氟化工产品项目评估分析报告
- 投资学第7版 郎荣燊 思政大纲
- 2019粤教版 高中美术 选择性必修1 绘画《第二单元 练就创造美的巧手》大单元整体教学设计2020课标
- 2024届广西梧州柳州高考数学试题命题比赛模拟试卷
- 历史九年级上册《目录与课程标准》2022版
- 部编版语文五年级上册第六单元(复习课件)
- 石河子公交线路全集
- 【管理】朗诵《我骄傲-我是中国人》汇编课件
- (医学)骨标志物临床应用教学课件
- 红色绘本小故事爱国教育-长征路上的红小丫课件
- 点估计的评价标准
- 全国导游基础知识-中国四大宗教-佛教
- 内部控制案例第07章案例20 华为内控
- 深化设计方案(完整版)
- 厦门大学《细胞生物学》期末试题及答案
评论
0/150
提交评论