⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 85.txt

📁 VB文章集(含API、窗口、数据库、多媒体、系统、文件、等等)
💻 TXT
📖 第 1 页 / 共 2 页
字号:
萤幕抓取与萤幕保护程式 


王国荣

「VB 没有提供这样的功能, 必须呼叫 Windows API」, 当笔者这样回答读者之後,有些读者会要求笔者介绍 Windows API 方面的书籍, 尤其是中文书, 但实际上,目前市面上只看到一本原文书(ZD Press 出版的 Visual Basic 5.0 Programming Guide to Win32 API), 中文书则未见过, 为什麽没有 Windows API 方面的中文书呢?道理很简单, Windows API 对 VB 的学习者而言, 犹如山峰之颠, 能够一路爬上来的人原本就十分有限,而越往山顶, 人烟越稀少, 因此这样的书写出来, 销售成绩必然惨不忍睹, 也许有些读者会觉得本土的作者实在很混,只愿意写简单的书, 但撰写深入的书籍, 费时费力费神而销售成绩又不好, 最终结果是这种不混的作者混不下去,当过读者而现在又是作者的笔者, 对於此一现象有时也颇感无奈。

不管怎样, 笔者现在已经开始介绍 Windows API 了, 也许真的不想混了,但混与不混不是笔者开启本系列讲座最担心的事情, 笔者所担心的是这样的主题对读者来说会不会太枯燥?会不会太艰涩?会不会像笔者当初研读 Windows API 时, 越研读心中的疑问越多, 就好像进入无底黑洞一样?

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

本期笔者想引领您去的地方是:萤幕抓取程式与萤幕保护程式。


--------------------------------------------------------------------------------
萤幕抓取程式简介 
--------------------------------------------------------------------------------

如果不写程式, 抓取萤幕图像的方法是:按下 Print Screen 键, 然後开启 Windows 的小画家, 接着选取小画家功能表的「编辑/贴上」, 即可将萤幕图像复制到小画家的绘图区域中。 

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

图-1「萤幕抓取程式」


--------------------------------------------------------------------------------
萤幕保护程式简介 
--------------------------------------------------------------------------------

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

如何撰写萤幕保护程式当然也是本期的重点, 同样的, 介绍以前, 请进入笔者的网站下载笔者所撰写的萤幕保护程式(saver.vbp),此一程式预设的等待时间是 0.5 分钟, 如果您等待 30 秒不操作键盘与滑鼠,程式便会进入萤幕保护状态, 您也可以设定等待的时间, 如图-2, 或者直接按下「立刻测试」钮以检视萤幕保护程式的动画。(特别注意:请务必以程式右上角的关闭钮结束程式,不要以 VB 的结束钮来结束程式, 否则…, 玩看看, 就知道会有什麽後果) 

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

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


--------------------------------------------------------------------------------
Windows 的绘图观念 
--------------------------------------------------------------------------------

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

绘图之前, 先取 hDC 
--------------------------------------------------------------------------------

所有 Windows 的绘图, 都必须先取得 hDC, 然後以 hDC 呼叫绘图的 API。hDC 是 handle of DC(Device Context) 的缩写, 有关 handle 的观念笔者上一期已经有所说明,本期不再重述, 至於 DC 呢?Windows 规定任何程式绘图之前都必须先配置一块绘图专用的系统资源(通常是记忆体),这绘图专用的系统资源就是 DC 啦。DC 与其他系统资源一样, 会有一个唯一的 handle 值, 此一 handle 值便是 hDC。

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

BitBlt:图像描绘函数 
--------------------------------------------------------------------------------

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

Form1.PaintPicture Picture1.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 预先帮我们准备好的, 在萤幕抓取及保护程式中,我们则必须呼叫 Windows API 取得萤幕的 DC, 如此方可读取萤幕的图像, 以及复制图像到萤幕上。取得萤幕 DC 的函数是 GetDC, 呼叫之叙述如下:

Dim hDC As Long
hDC = GetDC(0)

传回值 hDC 即等於萤幕的 hDC。在此笔者顺便要说明 Windows 另一个重要的观念:系统资源不用时应释回,所以在我们取得萤幕 DC, 并且完成绘图之後, 别忘了将 DC 释回, 此时呼叫的 API 是:

' hDC 是先前 GetDC(0) 的传回值
ret = ReleaseDC(0, hDC)

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

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

Dim hDC As Long
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 ' 设定自动重绘
...
... 连续性的绘图动作
...
Set Form名.Picture = Form名.Image ' 将表单的图像设定成常驻性的图片
Form名.AutoRedraw = False ' 取消自动重绘

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -