编程高手之路跟我学VB萤幕抓取与萤幕保护程式.docx

上传人:b****4 文档编号:3780140 上传时间:2022-11-25 格式:DOCX 页数:9 大小:64.21KB
下载 相关 举报
编程高手之路跟我学VB萤幕抓取与萤幕保护程式.docx_第1页
第1页 / 共9页
编程高手之路跟我学VB萤幕抓取与萤幕保护程式.docx_第2页
第2页 / 共9页
编程高手之路跟我学VB萤幕抓取与萤幕保护程式.docx_第3页
第3页 / 共9页
编程高手之路跟我学VB萤幕抓取与萤幕保护程式.docx_第4页
第4页 / 共9页
编程高手之路跟我学VB萤幕抓取与萤幕保护程式.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

编程高手之路跟我学VB萤幕抓取与萤幕保护程式.docx

《编程高手之路跟我学VB萤幕抓取与萤幕保护程式.docx》由会员分享,可在线阅读,更多相关《编程高手之路跟我学VB萤幕抓取与萤幕保护程式.docx(9页珍藏版)》请在冰豆网上搜索。

编程高手之路跟我学VB萤幕抓取与萤幕保护程式.docx

编程高手之路跟我学VB萤幕抓取与萤幕保护程式

编程高手之路—跟我学VB—萤幕抓取与萤幕保护程式

「VB没有提供这样的功能,必须呼叫WindowsAPI」,当笔者这样回答读者之後,有些读者会要求笔者介绍WindowsAPI方面的书籍,尤其是中文书,但实际上,目前市面上只看到一本原文书(ZDPress出版的VisualBasic5.0ProgrammingGuidetoWin32API),中文书则未见过,为什麽没有WindowsAPI方面的中文书呢?

道理很简单,WindowsAPI对VB的学习者而言,犹如山峰之颠,能够一路爬上来的人原本就十分有限,而越往山顶,人烟越稀少,因此这样的书写出来,销售成绩必然惨不忍睹,也许有些读者会觉得本土的作者实在很混,只愿意写简单的书,但撰写深入的书籍,费时费力费神而销售成绩又不好,最终结果是这种不混的作者混不下去,当过读者而现在又是作者的笔者,对於此一现象有时也颇感无奈。

不管怎样,笔者现在已经开始介绍WindowsAPI了,也许真的不想混了,但混与不混不是笔者开启本系列讲座最担心的事情,笔者所担心的是这样的主题对读者来说会不会太枯燥?

会不会太艰涩?

会不会像笔者当初研读WindowsAPI时,越研读心中的疑问越多,就好像进入无底黑洞一样?

为了避免以上的结果,在内容的介绍上,笔者会倾向於即学即用的API,短期内尽量避免深入Windows无底黑洞地带,而会先到那些有花有草地方。

本期笔者想引领您去的地方是:

萤幕抓取程式与萤幕保护程式。

萤幕抓取程式简介

如果不写程式,抓取萤幕图像的方法是:

按下PrintScreen键,然後开启Windows的小画家,接着选取小画家功能表的「编辑/贴上」,即可将萤幕图像复制到小画家的绘图区域中。

 

如果写程式呢?

稍後笔者就会介绍,介绍以前,建议您先进入笔者的网站下载笔者所撰写的萤幕抓取程式(CopyScr.vbp),一来可了解程式的基本运作模式,二来不必自己输入程式,此一程式执行後,选取功能表的「我抓我抓我抓抓」,即可将萤幕的图像复制进来。

图-1「萤幕抓取程式」

萤幕保护程式简介

保护萤幕最简单的方法就是不用时关掉它,但有这种好习惯的人实在不多,所以有人写程式侦测滑鼠与键盘的输入,如果有一段时间没有滑鼠或键盘的输入,便将电脑视为没有人在使用,而把萤幕显示成黑色,用以保护萤幕,後来又有人觉得黑色太难看了,就加了一点动画,慢慢地动画越来越多也越有趣,结果反倒成为萤幕保护程式不可或缺的功能,而不再以保护萤幕为主了。

如何撰写萤幕保护程式当然也是本期的重点,同样的,介绍以前,请进入笔者的网站下载笔者所撰写的萤幕保护程式(saver.vbp),此一程式预设的等待时间是0.5分钟,如果您等待30秒不操作键盘与滑鼠,程式便会进入萤幕保护状态,您也可以设定等待的时间,如图-2,或者直接按下「立刻测试」钮以检视萤幕保护程式的动画。

(特别注意:

请务必以程式右上角的关闭钮结束程式,不要以VB的结束钮来结束程式,否则…,玩看看,就知道会有什麽後果) 

图-2「萤幕保护程式」的设定画面

了解萤幕抓取程式及萤幕保护程式的基本运作模式,接下来让笔者来说明相关的工作概念。

Windows的绘图观念

VB用来绘图的方法有Line(画线及矩形)、Circle(画圆)、PSet(画点)、PaintPicture(描绘图片)…等,这些方法有一共通特点—只能描绘在表单(Form)视窗的「显示区域」(Windows称之为clientrectangle),想跨越显示区域而把文字或图形描绘在视窗标题区、功能表区、萤幕任意区域…,想都别想,而以萤幕保护程式为例,则必须在萤幕任意位置绘图。

想在萤幕任意位置绘图,我们必须先了解Windows的绘图观念

绘图之前,先取hDC

所有Windows的绘图,都必须先取得hDC,然後以hDC呼叫绘图的API。

hDC是handleofDC(DeviceContext)的缩写,有关handle的观念笔者上一期已经有所说明,本期不再重述,至於DC呢?

Windows规定任何程式绘图之前都必须先配置一块绘图专用的系统资源(通常是记忆体),这绘图专用的系统资源就是DC啦。

DC与其他系统资源一样,会有一个唯一的handle值,此一handle值便是hDC。

VB程式呼叫Line、Circle、Pset、PaintPicture…等方法时,表面上好像与DC无关,但实际上它们都会预先配置好DC,然後透过DC来绘图,您可以查阅表单及PictureBox物件的说明文件,结果可以发现它们都含有hDC属性,此一属性即为表单及PictureBox物件用来呼叫Windows绘图函数的DChandle。

BitBlt:

图像描绘函数

二话不说,让我们直接观察一个利用DC来绘图的API函数—BitBlt,BitBlt的作用与PaintPicture有点类似,假设表单上含有一PictureBox,而此一PictureBox的Picture属性亦设定有图片,若使用VB的绘图功能,则将PictureBox的图片绘制在Form1的方法是:

Form1.PaintPicturePicture1.Picture,0,0 

如果使用BitBlt函数则是:

ret=BitBlt(Form1.hDC,0,0,Picture1.Width,Picture1.Height,Picture1.hDC,0,0,SRCCOPY)

作用是把Picture1的图像复制到Form1,使用此一函数时,请特别注意参数四(如以上叙述之Picture1.Width)及参数五(如以上叙述之Picture1.Height),这两个参数分别表示长与宽,但单位是「像素」(pixel),所以执行以上叙述之前,必须先把表单的ScaleMode属性都设定成"3-像素"才可以,此一BitBlt函数之使用实例请参阅笔者所完成的BitBlt.vbp(包含在下载之档案中)。

 

萤幕hDC的取得与释回

表单及PictureBox物件的DC是VB预先帮我们准备好的,在萤幕抓取及保护程式中,我们则必须呼叫WindowsAPI取得萤幕的DC,如此方可读取萤幕的图像,以及复制图像到萤幕上。

取得萤幕DC的函数是GetDC,呼叫之叙述如下:

DimhDCAsLong

hDC=GetDC(0)

传回值hDC即等於萤幕的hDC。

在此笔者顺便要说明Windows另一个重要的观念:

系统资源不用时应释回,所以在我们取得萤幕DC,并且完成绘图之後,别忘了将DC释回,此时呼叫的API是:

'hDC是先前GetDC(0)的传回值

ret=ReleaseDC(0,hDC)

将萤幕图像复制到VB物件中

介绍BitBlt及GetDC两个API函数之後,萤幕抓取程式几乎是呼之欲出了,例如使用以下的叙述可以将萤幕图像复制到表单物件上:

 

DimhDCAsLong

hDC=GetDC(0)

ret=BitBlt(Form1.hDC,0,0,萤幕宽,萤幕高,hDC,0,0,SRCCOPY)

ret=ReleaseDC(0,hDC)

不过请注意「萤幕宽」及「萤幕高」两个参数,这两个参数的长度单位是「像素」,以640×480的萤幕为例,应该指定成640及480,但问题是别人使用的萤幕可能不是640×480,所以我们应该利用Screen物件的Width及Height属性读取萤幕的宽与高(注:

此时读取之宽与高是以Twips为单位),然後再利用以下公式求取萤幕以pixel为单位的宽与高:

 

pixel单位之萤幕宽=Screen.Width\Screen.TwipsPerPixelX

pixel单位之萤幕高=Screen.Height\Screen.TwipsPerPixelY

将萤幕图像复制到表单上面的完整程式,请参阅笔者所完成的ScrForm.vbp(包含在下载之档案中)。

萤幕抓取程式之制作

接着请以笔者所完成的CopyScr.vbp来例,让我们来了解萤幕抓取程式还有哪些地方该注意。

 

AutoRedraw(自动重绘)属性的使用

首先笔者想请您做个实验:

执行ScrForm.vbp程式,并且复制萤幕图像到表单上,接着以其他视窗盖住此一表单,然後再移开,结果表单上曾经被盖住的区域其图像都会消失。

解决以上问题常用的方法是将表单的AutoRedraw(自动重绘)属性设定为True,当我们将表单的AutoRedraw属性设定为True之後,将来表单若有区域被覆盖住而又回到萤幕前端,则表单都会自动重绘被覆盖的区域,使得表单能够展现原有的图像。

利用AutoRedraw属性来解决以上的问题看起来十分简单,但它有个严重的缺点:

当我们将表单的AutoRedraw属性设定为True之後,表单将会记录每一个绘图的动作,而当绘图动作越来越多时,所使用的记忆体将会逐渐增加,自动重绘的时间也会越来越长。

为了改善以上的缺点,笔者的作法如下:

Form名.AutoRedraw=True'设定自动重绘

...

...连续性的绘图动作

...

SetForm名.Picture=Form名.Image'将表单的图像设定成常驻性的图片

Form名.AutoRedraw=False'取消自动重绘

由於Picture属性中的图片是常驻的,因此当我们将表单的Image属性(等於表单上的图像)设定给它,便可以将AutoRedraw属性设定为False,以避免不必要的重绘动作。

 

以上程式使用了AutoRedraw、Image、及Picture属性,这些属性除了适用於表单物件之外,也适用於PictureBox物件,而实际上,笔者所撰写的CopyScr.vbp并不是把萤幕复制到表单上,而是复制到PictureBox物件之中。

浏览图片的操作介面

除了将萤幕图像复制到PictureBox之外,另一个问题则是萤幕总是比表单的显示区域来得大,以致被复制到PictureBox的图像会超出表单的显示区域,为了让使用者可以看到萤幕的全貌,我们必须在表单上布置卷动轴,并提供浏览的操作介面。

 

有关大图片浏览程式,常见的作法是把显示图片的PictureBox布置在另一个PictureBox里面,然後再利用卷动轴调整内部PictureBox相对於外部PictureBox的位置,而达到浏览图片的目的,如图-3。

 

图-3图片浏览程式所需之控制元件及其布置

至於相关程式则请参考CopyScr.frm的SetPicture副程式、VScroll1_Change、及HScroll1_Change事件程序。

图片的存档 

最後就是图片的存档了,VB提供的存档叙述是SavePicture,呼叫格式如下:

 

SavePicture图片,档案名称

其中「图片」参数可以是物件的Picture属性或利用LoadPicture所载入的Picture物件,以本程式为例,则指定成PictureBox的Picture属性。

萤幕保护程式的制作

笔者所撰写的萤幕保护程式,是将萤幕切割成M×N个方块,然後在萤幕保护程式启动时,随机变换任意两个方块,此时所需执行的动作是:

(1)将(M1,N1)座标的方块复制到一暂存区。

(2)将(M2,N2)座标的方块复制到(M1,N1)座标。

(3)将暂存区的方块复制到(M2,N2)座标。

假设每一方块的边长等於80,则所需执行的BitBlt叙述如下:

 

'hDCMem为暂存区之hDC

'hDCScreen为萤幕之hDC

ret=BitBlt(hDCMem,0,0,80,80,hDCScreen,M1*80,N1*80,SRCCOPY)

ret=BitBlt(hDCScreen,M1*80,N1*80,80,80,hDCScreen,M2*80,M2*80,SRCCOPY)

ret=BitBlt(hDCScreen,M2*80,M2*80,80,80,hDCMem,0,0,SRCCOPY) 

暂存区DC的取得与释回

在以上程式中,hDCScreen是利用GetDC(0)取得,而hDCMem(暂存区的DC)则必须利用CreateCompatibleDC函数来取得,如下:

 

DimhDCMemAsLong

hDCMem=CreateCompatibleDC(hDCScreen)

此一函数的作用是建立相容性DC,由於传入的是hDCScreen(萤幕的hDC),所以建立出来的hDCMem将与萤幕相容(主要是色盘之颜色数目相同)。

暂存区DC不再使用时应将其释回,此时呼叫之API是DeleteDC,如下:

(释回萤幕DC的函数是ReleaseDC,两者不可以混合使用)

ret=DeleteDC(hDCMem)

CreateCompatibleBitmap:

为DC建立点阵图 

取得hDCMem之後,利用BitBlt应该就可以将hDCScreen的图像复制到暂存区DC中,但实际上不然,BitBlt只对含有「点阵图」(Bitmap)的DC有作用,而经由CreateCompatibleDC所建立的暂存区DC一开始是不含点阵图的,所以呼叫BitBlt函数并没有作用,为了让BitBlt能够复制图像到暂存区DC,以及从暂存区DC读取图像,我们必须为暂存区DC建立点阵图,此时呼叫之API如下:

 

DimhBitmapAsLong

hBitmap=CreateCompatibleBitmap(hDCScreen,宽,高)'建立点阵图

ret=SelectObject(hDCMem,hBitmap)'将点阵图设定给hDCMem

请特别注意传入CreateCompatibleBitmap的hDC是萤幕的hDC,不是暂存区的hDC,其作用是建立与萤幕相容的点阵图(颜色数目与萤幕相同的点阵图),而接下来必须呼叫SelectObject让此一点阵图的handle(hBitmap)附属於hDCMem,也就是让暂存区DC含有点阵图,如此一来hDCMem方可用於BitBlt函数。

点阵图的释回 

不使用点阵图时,可呼叫DeleteObject(hBitmap)将其释回,但请注意附属於DC的点阵图是不可以释回的,除非DC也已经被释回系统,例如:

'hBitmap附属於hDCMem

ret=DeleteDC(hDCMem)'先释回DC

ret=DeleteObject(hBitmap)'再释回点阵图

萤幕保护程式之动画 

使用以上所介绍的API函数,总算可以达到随机变换萤幕任意两个方块的目的了,请看笔者所完成的副程式:

(此一副程式放置saver.vbp专案的saver.bas档案中,也包含在下载的档案中)

SubSaver()

DimM1AsLong,M2AsLong,N1AsLong,N2AsLong,retAsLong

DimhDCMemAsLong,hDCScreenAsLong,hBitmapAsLong

DimsxAsInteger,syAsInteger

sx=Screen.Width\Screen.TwipsPerPixelX'以pixel为单位之萤幕宽

sy=Screen.Height\Screen.TwipsPerPixelY'以pixel为单位之萤幕高

hDCScreen=GetDC(0)'取得萤幕DC

hDCMem=CreateCompatibleDC(hDCScreen)'建立暂存区DC

hBitmap=CreateCompatibleBitmap(hDCScreen,BSize,BSize)'建立点阵图

ret=SelectObject(hDCMem,hBitmap)'将点阵图设定给暂存区DC

M1=CInt(Rnd*sx\BSize)

N1=CInt(Rnd*sy\BSize)'(M1,N1)为方块一

M2=CInt(Rnd*sx\BSize)

N2=CInt(Rnd*sy\BSize)'(M2,N2)为方块二

'方块一与方块二互换

ret=BitBlt(hDCMem,0,0,BSize,BSize,hDCScreen,M1*BSize,N1*BSize,SRCCOPY)

ret=BitBlt(hDCScreen,M1*BSize,N1*BSize,BSize,BSize,hDCScreen,M2*BSize,N2*BSize,SRCCOPY)

ret=BitBlt(hDCScreen,M2*BSize,N2*BSize,BSize,BSize,hDCMem,0,0,SRCCOPY)

ret=ReleaseDC(0,hDCScreen)'释回萤幕DC

ret=DeleteDC(hDCMem)'释回暂存区DC

ret=DeleteObject(hBitmap)'释回点阵图,一定要放在DeleteDC之後

EndSub

有了Saver副程式,再配合连续的变换动作,这就是笔者所制作的萤幕保护程式动画。

 

键盘及滑鼠的侦测 

当萤幕保护程式进入动画时,程式必须侦测使用者是否有操作键盘或滑鼠,如果有,则终止动画,并且将萤幕还原,而当程式离开动画或尚未进入动画时,必须侦测使用者没有操作键盘或滑鼠的时间是否超过等待时间,如果是,则进入动画。

但是在Windows的多工作业环境底下,所有键盘及滑鼠的输入是由Windows统筹管里的,当使用者操作键盘或滑鼠时,键盘与滑鼠的接收者是Windows,而Windows会根据当时的情况,决定键盘及滑鼠的输入该传给哪一个程式或视窗,因此每一个程式或视窗只会收到属於自己的键盘及滑鼠输入。

以上的运作模式就好像电话一样,正常情况之下,每个人都只会收到属於自己的电话,除非,嘿嘿,窃听。

在Windows的工作模式底下,想要窃听键盘及滑鼠的输入是可能的,一旦窃听成功,属於其他视窗的键盘及滑鼠输入都会先传到我们的程式中。

有关窃听方面的程式设计,笔者想留待下一回再介绍,因为必须说明的观念实在不少,本期请直接使用笔者所完成的键盘及滑鼠侦测程式—Saver.vbp中的hook.bas模组,此一模组虽然没有提供窃听的功能,但可以侦测到是否有键盘及滑鼠被输入(不管输入的对象是哪一个程式或视窗都可以侦测到)。

使用hook.bas的方法如下:

1.侦测键盘及滑鼠的输入之前,呼叫StartHook副程式。

2.呼叫StartHook之後,只要发生键盘或滑鼠的输入,hook模组便会将键盘或滑鼠被输入的时间记录在tmKbMouse全域变数中,其他程式可以利用目前时间(呼叫Now函数)减去此一变数,得知使用者隔多久没有操作键盘及滑鼠了,如果超过等待时间,便可以进入萤幕保护程式的动画。

3.进入萤幕保护程式的动画之前,记得把hook.bas的KbMouseDetect全域变数设定为False,接着进入萤幕保护状态之後,只要使用者再度操作键盘或滑鼠,此一变数便会被hook.bas模组设定True,而其他程式可以再判断此一变数,以停止动画并还原萤幕。

4.萤幕保护程式结束以前一定要呼叫FreeHook副程式,不然会造成Windows运作不正常,举例来说,笔者所撰写的saver.frm中便是在Form_Load事件程序中呼叫StartHook,在Form_Unload事件程序中呼叫FreeHook。

萤幕的还原

当萤幕保护程式停止动画时,我们必须把萤幕还原,还原的方法有很多种,例如启动动画之前先储存萤幕的图像,结束时再回存图像,不过这个方法比较浪费记忆体,笔者使用的方法是把表单隐藏起来,然後再显示出来,接着放到最大,然後恢复成原大小,作用是利用表单覆盖整个萤幕,则最後当表单又恢复成原大小时,萤幕图像即会自动还原,程式如下:

SubRestoreScreen()

Me.Visible=False

Me.Visible=True

Me.WindowState=vbMaximized

Me.WindowState=vbNormal

EndSub

时间的控制

除了saver及hook两个模组之外,最重要的事情就是时间的控制了,在笔者的saver表单中,布置了两个Timer控制元件(Timer1及Timer2),其中Timer2用来侦测使用者隔多久没有操作键盘及滑鼠,若超过等待时间,则驱动Timer1进入动画描绘状态,其程式如下:

PrivateSubTimer2_Timer()

IfDateDiff("s",tmKbMouse,Now)>WaitTime*60Then

Timer1.Interval=10'驱动动画

EndIf

EndSub

至於Timer1则是用来显示动画,并判断使用者是否操作了键盘及滑鼠以决定是否中断动画,程式如下:

PrivateSubTimer1_Timer()

IfNotStartSaverThen'进入动画的初始动作

StartSaver=True

KbMouseDetect=False

ExitSub

EndIf

IfKbMouseDetectThen'用者操作了键盘或滑鼠

Timer1.Interval=0

StartSaver=False

RestoreScreen'还原萤幕

Else

Saver'显示动画

EndIf

EndSub

制作您自己的萤幕保护程式

以上介绍的是笔者所制作的萤幕保护程式,虽然动画的部分稍嫌简单,但Windows技术的难处均已克服,如果您想制作自己的萤幕保护程式,需要修改的是动画的部分,也就是saver.bas中的saver副程式,此外,萤幕

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1