【VB开源代码栏目提醒】:网学会员为广大网友收集整理了,VB屏幕保护程序设计 - 大学课件,希望对大家有所帮助!
屏幕保护程序设计 屏幕保护程序简单功能实现 2.5.1 文字单向移动功能实现 本屏幕保护程序的主体功能是文字在屏幕左右移动首先需要在屏幕上显示文字。
对于Visual Basic程序而言在屏幕上显示文字实际上是显示在某个窗口上。
显示文字可以采用两种方法第一种方法是直接在窗口某个位置输出文字这种方法需要调用某个函数或窗口对象的方法并指定坐标如果改变其位置则需要在新位置重新输出文字并且将原来位置的文字擦除这种文字输出在设计时看不到效果只有运行程序时才能看到效果第二种方法是采用某个对象显示文字文字的移动仅仅需要改变该对象的位置即可并且在设计时就能够看到效果。
这里采用第二种方法显示文字即采用前面介绍的标签对象显示文字。
创建一个新的Visual Basic工程系统自动创建一个窗口对象Form1并显示Form1的对象设计窗口。
向窗口Form1上拖放一个标签对象系统自动命名为Label1最后一个字符为数字1倒数第二个字符为小写字母l 。
Visual Basic集成开发环境自动以数字后缀对新创建的控件对象命名对下一个标签命名为Label2选中该对象定位到属性窗口修改Label1对象的属性 Caption 欢迎使用Visual Basic Font宋体二号字 给Cpation赋值的内容实际是一个字符串在属性窗口内赋值时不能在其前后加上双引号。
如果在
代码窗口内赋值则需要加上双引号。
调整Label1的长度和高度使得文字正好显示在一行。
图2.4 标签Label1的设计效果 标签对象Label1在窗口Form1上的位置由其Left和Top属性确定如果需要在水平方向移动实际就是改变其Left属性。
先采用人工移动的方式即运行时每用鼠标点击一次文字文字向右移动一定的距离。
运行时的鼠标点击变成了Windows系统的消息并转换成Visual Basic中的事件在哪个对象上点击哪个对象就会接收到这个点击事件Visual Basic自动调用特定的某个子程序。
Visual Basic用Click表示鼠标点击事件鼠标的一次点击也称为单击事件如果在Label1对象上单击则Label1对象接收到这个单击事件并自动调用子程序Label1_Click。
为了编写子程序Label1_Click需要进入
代码窗口方法有三个 选择工程资源管理器窗口上方最左侧图标View Code 选择“View”菜单下“Code”子菜单 双击Form1的对象
设计窗口 在
代码窗口上方的两个组合框中分别选择对象Label1和事件Click则自动产生该子程序的框架。
由于Click事件是标签对象的默认事件只要选择了Label1就会自动产生该子程序框架。
另外如果在对象设计窗口中直接双击Label1对象进入
代码窗口后自动产生该子程序框架。
定位到子程序框架内部输入
代码如下 Private Sub Label1_Click Label1.Left Label1.Left 100 End Sub 这句
代码的含义是每次点击Label1对象其Left属性在原有基础上增加100实际效果就是向右移动100单位就是前面介绍的Twip1/1440英寸。
选择“Run”菜单下的“Start”子菜单或直接点击工具栏上的小图标运行该程序。
图2.5即为运行开始以及单击文字几次以后的文字位置。
图2.5 标签Label1的运行效果 如果能够在某个特定的时间内自动执行上面这样的子程序就可以实现文字的自动移动。
Visual Basic提供的定时器对象可以实现这样的功能。
切换到对象设计窗口有两种方法 选择工程资源管理器窗口上方中间图标View Object 选择“View”菜单下“Object”子菜单 向窗口Form1上拖放一个定时器控件自动命名为Timer1修改其属性 Interval100 EnabledTrue 双击Timer1对象进入
代码窗口并自动产生子程序框架Timer1_Timer将Label1_Click子程序中的
代码拷贝到子程序Timer1_Timer中。
Private Sub Timer1_Timer Label1.Left Label1.Left 100 End Sub 重新运行该程序则文字会自动向右移动如果需要改变文字移动的速度可以改变Timer1对象的Interval也可以修改上述
代码中的移动量100。
对于上面的两个子程序都是由系统在接收到相应事件后自动调用的程序员自己编写的
代码中并没有调用它们的地方。
这样的事件处理子程序除了由
系统自动调用外也可以由程序员指定调用。
例如上述两个子程序的内容实际是一致的没有必要重复写两次完全可以由一个子程序调用另外一个子程序将上述程序修改如下 Private Sub Label1_Click Timer1_Timer End Sub 在子程序Label1_Click中调用子程序Timer1_Timer。
程序运行效果与前面程序一致。
由于在定时器内实现文字移动人工移动的子程序Label1_Click实际上已经没有用了完全可以删除掉。
如果不删除该子程序则既可以自动移动也可以人工移动。
2.5.2 文字双向移动功能实现 到目前为止实现了文字的自动移动但当文字移动到窗口最右侧后看不到文字了需要将其反向向左移动。
从前面程序已知向右移动是Label1的Left属性每次加上一个数值100向左移动则应该是Label1的Left属性每次减去一个数值100。
那什么时候该减呢应该是在文字的最右端碰上窗口的右边框时为此需要判断文字是否超出窗口右边框。
标签Label1只有Left属性而没有Right属性但其提供了Width属性Left属性加上Width属性就是Label1对象的最右侧Label1.LeftLabel1.Width。
前面已经介绍过窗口对象Form1的宽度采用Width属性表示但文字是在其客户区内移动这里需要采用其ScaleWidth属性。
在子程序Timer1_Timer内采用If语句比较Label1.LeftLabel1.Width与Form1.ScaleWidth形式如下 If Label1.Left Label1.Width gt Form1.ScaleWidth Then End If 标签Label1的Left属性每次减100的
代码应该写在哪里很多人的第一感觉就是写在上面的这个条件语句内如下所示 Private Sub Timer1_Timer Label1.Left Label1.Left 100 If Label1.Left Label1.Width gt Form1.ScaleWidth Then Label1.Left Label1.Left - 100 End If End Sub 程序运行时发现开始文字可以正确地向右移动移动到某个位置后文字停止说明上述程序逻辑存在问题。
分析上述
代码在每个时间间隔100毫秒达到时Label1的Left属性首先加上100然后判断Label1的最右侧是否超过窗口Form1的宽度如果超过则将Label1的Left属性减去100。
开始阶段由于条件不满足每个时间间隔内Label1的Left属性都加100文字正常向右移动。
当Label1的最右侧超过窗口宽度时仍然是先将Label1的Left属性加上100再根据条件将其减去100则在一个时间间隔内Label1的Left属性没有发生如何变化导致文字停止。
于是有些人的想法是将减去100改成减去200希望实现向左移动。
运行程序后发现文字在某个位置附近来回移动并没有实现真正的向左移动。
究其原因在条件满足后Label1的Left属性减去200文字向左移动了100下一个时间间隔内条件变成了不满足Label1的Left加100文字又向右移动再次满足条件导致文字在该位置附近100范围内来回移动。
要实现真正的文字正反移动一定要保证Label1的Left属性在某个时间间隔内只能变化一次要么加100要么减100。
为此需要引入移动方向正方向移动时Label1的Left属性每次加100反方向移动时Label1的Left属性每次减100。
这样的移动方向采用变量表示即需要定义一个变量表示文字的移动方向。
对于文字的左右移动只有两个移动方向即变量只有两个取值。
由前面的变量类型介绍已知Visual Basic的Boolean类型取值为True和False两个值可以满足当然也可以采用Byte、Integer等类型。
选择Boolean类型变量时可以人为规定该变量为False时文字由左向右移动该变量为True时文字由右向左移动。
如果选择Byte类型变量可以人为规定变量为0时表示由左向右移动变量为1时表示由右向左移动。
这个变量如果定义在子程序Timer1_Timer内部则是一个局部变量或称过程变量每次调用这个子程序时需要重新申请内存保存它其值为0而调用结束时又释放其占用的内存区域不能保留上次调用该子程序时该变量的值。
本程序中该变量必须能够保留上次的值可以将其定义为窗体变量即定义在窗口Form1的所有子程序之前某个窗口的窗体变量都必须定义在所有子程序的最前面。
有了表示方向的变量后在子程序Timer1_Timer内必须根据方向变量的值决定Label1的Left属性是加100还是减100。
正方向移动时要判断Label1的Left属性与Width属性之和是否超过窗口Form的ScaleWidth属性如果超过则改变方向反方向移动时判断Label1的Left属性是否小于0如果小于则改变方向。
实现
代码如下所示 Dim ReverseDirection As Boolean Private Sub Timer1_Timer If ReverseDirection False Then Label1.Left Label1.Left 100 If Label1.Left Label1.Width gt Form1.ScaleWidth Then ReverseDirection True End If Else Label1.Left Label1.Left - 100 If Label1.Left lt 0 Then ReverseDirection False End If End Sub 上述
代码中变量ReverseDirection用于表示移动方向这个变量名称可以任意指定只要编程者自己明白即可。
这里采用了嵌套的If条件语句外层If条件是移动方向判断第一个内层If条件是判断是否超过窗口右边界第二个内层If条件是判断是否超过窗口左边界采用了简化格式条件和执行语句写在一行这种情况下不能再写End If。
像这样的嵌套语法应该采用缩进格式即每层都向右缩进几个字符位置一般为2个字符位置。
运行程序可以实现文字的左右来回移动但还存在一个小
问题文字的最右侧并没有达到窗口右边界就开始返回了。
从前面的
代码可以看出文字方向改变的条件判断是以Label1对象的Left和Width属性进行的而Label1上显示的文字宽度与Label1本身宽度并不一致。
可以在对象设计窗口上人工调整Label1的大小使其宽度与文字宽度一致也可以设置Label1的AutoSize属性使得其大小与文字大小一致。
如果希望实现文字的上下移动只需要将上述
代码中的Left改成Top将Width改成Height即可。
2.5.3 文字大小与颜色效果实现 除了文字的左右移动外简单屏幕保护程序还需要实现文字大小和颜色变化。
文字的大小调整是针对其FontSize属性使其在10和50之间变化而颜色变化则针对其ForeColor属性每次采用随机颜色。
文字由小到大与由大到小的变化与文字的左右移动类似也需要定义一个变量表示其变化方向。
这个变量也可以定义成Boolean类型和其它类型下面
代码将其定义成Byte类型用0表示文字由小到大变化用1表示文字由大到小变化变量名称也取成简单的D1。
需要说明的是由于文字左右移动与大小变化并不能同步只能采用两个不同的变量分别表示。
文字的颜色变化采用前面介绍的RGB与Rnd函数由Rnd函数产生三个0 到255随机整数分别代表红色、绿色和兰色的比例。
另外需要在窗口的Load事件对应的处理子程序Form_Load中加入Randomize函数调用语句。
实现上述功能的
代码如下 Dim ReverseDirection As Boolean Dim D1 As Byte Private Sub Form_Load Randomize End Sub Private Sub Timer1_Timer If ReverseDirection False Then Label1.Left Label1.Left 100 If Label1.Left Label1.Width gt Form1.ScaleWidth Then ReverseDirection True End If Else Label1.Left Label1.Left - 100 If Label1.Left lt 0 Then ReverseDirection False End If If D1 0 Then Label1.FontSize Label1.FontSize 2 If Label1.FontSize gt 50 Then D1 1 Else Label1.FontSize Label1.FontSize - 2 If Label1.FontSize lt 10 Then D1 0 End If Label1.ForeColor RGB255 Rnd 255 Rnd 255 Rnd End Sub 图2.6所示为简单屏幕保护程序运行过程中文字变化的截图。
图2.6 文字动态变化效果图 2.5.4屏幕保护程序结束功能实现 普通窗口可以通过标题栏上的关闭按钮结束程序而屏幕保护程序运行时没有标题栏也就不能点击关闭按钮。
Visual Basic提供了一个结束应用程序的语句End。
在需要结束屏幕保护程序的子程序中调用End语句即可。
屏幕保护
程序一般是在移动鼠标或按键时结束。
为此需要对窗口对象Form1的KeyDown事件和MouseMove事件进行处理编写如下的子程序。
Private Sub Form_KeyDownKeyCode As Integer Shift As Integer End End Sub Private Sub Form_MouseMoveButton As Integer Shift As Integer X As Single Y As Single End End Sub 比较上面
代码中子程序名称
代码与前面子程序名称的区别对Label1和Timer1对象其事件处理子程序名称由对象名称_事件名称组成如Label1_Click和Timer1_Timer而窗口处理子程序名称则由Form_事件名称组成这是因为在某个窗口内只有一个Form类型的对象代表窗口本身不需要再用类似于Form1或Form2这样的名称加以区分。
这种命名方式只适用于事件处理子程序在某个子程序内部使用窗口对象时仍然采用具体的Form1、Form2这样的名称其原因是在某个窗口内部的子程序中可以使用其它窗口对象的属性、方法。
添加上述
代码以后在Visual Basic集成开发环境中使用鼠标选择菜单或工具栏图标运行程序发现程序刚一开始运行就自动结束了。
发生这个现象的原因在于用鼠标选择菜单或图标时不可能保证鼠标一点都不动也就是说肯定会产生鼠标移动事件从而使得屏幕保护程序一运行就接收到MouseMove事件系统自动调用上述的Form_MouseMove子程序结束程序。
为了解决这个问题可以采用两种方法 记录两次MouseMove的移动距离如果大于某个值就结束程序。
延时一段时间后再根据鼠标或键盘事件结束程序。
这里采用第二种方法。
窗口Form1中已经有了一个定时器Timer1它每隔100毫秒发生一次Timer事件可以记录发生Timer事件的次数产生需要的延时。
为了保证屏幕保护程序能够运行起来设置5秒的延时需要记录50次Timer事件可以定义一个Byte类型的变量保存Timer事件的次数。
由于需要延时一段时间才可以接收鼠标或键盘事件程序结束还需要定义一个Boolean类型变量表示是否可以结束。
Dim ReverseDirection As Boolean Dim D1 As Byte Dim QuitFlag As Boolean Dim N1 As Byte Private Sub Form_KeyDownKeyCode As Integer Shift As Integer If QuitFlag True Then End End Sub 上述
代码定义了两个新变量QuitFlag表示是否可以结束程序N1表示定时器Timer1对象的Timer事件发生次数它们都定义在所有子程序之前。
子程序Form_MouseMove中的
代码与Form_KeyDown中的
代码完全一致这里就不再列出。
记录定时器Timer1的Timer事件次数并设置QuitFlag标志的部分
代码如下 Private Sub Timer1_Timer N1 N1 1 If N1 50 Then QuitFlag True N1 0 End If If ReverseDirection False Then 其中的N10这条语句必须有否则每次发生Timer事件都计数当变量N1的值超过其表示范围时就会出错对于Byte类型的变量超过255就出错也就是说程序运行25.5秒后就会弹出如图2.7所示的提示窗口。
图2.7 变量N1超过255产生的出错提示 点击上图的“Debug”按钮进入
代码窗口以黄色标记出错的语句N1N11将鼠标光标放到变量N1上提示当前N1的值已经是255希望将N1再加1时超过Byte类型变量的表示范围如下所示 继续运行仍然会弹出图2.7所示窗口只能选择“End”结束。
2.5.5屏幕保护程序基本功能完善 上面的程序实际上仅仅是一个简单的Windows程序屏幕保护程序运行时往往具有如下特征占据整个屏幕黑色背景没有标题栏。
这些功能都可以通过Form对象的属性解决为此对Form1对象和Label1对象设置如表2.6所示的属性。
表2.6 Form1和Label1对象的主要属性设置 对象 属性 值 含义 Form1 BackColor 黑色 窗口背景为黑色 BorderStyle 0 没有边框和标题栏 WindowState 2 窗口运行时最大化占据整个屏幕 Label1 BackStyle 0 标签背景透明与窗口颜色一致 BackColor 除黑色外 黑色背景中能够显示文字 至此简单屏幕保护程序的基本功能已经实现。
将上面的工程保存起来。
选择“File”菜单的“Save Project”或“Save Project As”子菜单弹出如图2.8所示的窗口选择保存该工程的文件夹将工程文件名称改成SaveScreen.vbp。
如果是第一次保存在弹出图2.8所示窗口之前还会弹出图2.9所示的窗口用于选择文件夹和Form1保存文件名称如果工程存在多个窗口或模块则会弹出多个图2.9这样的窗口。
如果在图2.9中选择了文件夹则在图2.8中就没有必要在选择文件夹。
由于Visual Basic创建的每个工程都会有多个文件应该将它们保存在一个特定的文件夹中以便于管理可以先在Windows资源管理器中创建一个文件夹也可以在图2.8或图2.9中点击右上角右数第二个图标在当前文件夹中创建新的子文件夹。
图2.8 保存工程文件 图2.8 保存窗口文件 保存工程后如果程序输入没有任何错误可以将其编译成可执行文件选择“File”菜单的“Make SaveScreen.Exe”子菜单弹出图2.10所示的窗口。
图2.10 生成可执行文件窗口 图2.10默认将产生的可执行文件后缀设定成exe而屏幕保护程序的后缀为scr将图中的“SaveScreen.exe”改成“SaveScreen.scr”则会在选择的文件夹中产生文件SaveScreen.scr。
在资源管理器中找到该文件双击它运行效果如图2.11所示。
图2.11 直接运行SaveScreen.scr的效果 2.5.6屏幕保护程序安装与运行 将上面产生的SaveScreen.scr文件拷贝到C:WindowsSystem32文件夹下如图2.12所示。
图2.12 拷贝屏幕保护程序到指定文件夹 图2.13 选择屏幕保护程序 由图2.12可以看到当前系统中能够选择的屏幕保护程序都保存在该文件夹下所有屏幕保护程序都以.scr为后缀扩展名。
回到Windows桌面在空白区域点击鼠标右键从弹出菜单中选择“属性”进入显示属性对话框如图2.13所示选择“屏幕保护程序”选项卡点击下方的组合框从下拉框中可以看到拷贝过来的SaveScreen屏幕保护程序选择该项程序。
停止动作鼠标和键盘指定时间后桌面显示如图2.14的效果。
在桌面左下角出现一个标题为“Form1”的小窗口这就是我们设计的屏幕保护程序。
从图中效果来看这个屏幕保护程序并没有能够实现全屏黑背景显示文字动态效果功能与在Visual Basic中设计的效果不一致。
如果用鼠标双击一下左下角的小窗口可以弹出一个黑色背景窗口显示动态文字如图2.15。
图2.14 屏幕保护程序自动运行的效果 图2.15 双击小窗口后屏幕保护程序运行效果 这些现象表明采用Visual Basic编写的屏幕保护程序可以被Windows系统自动启动运行但其窗口的初始显示状态不对这是由于Windows屏保启动程序不能兼容Visual Basic的默认窗口显示方式将在2.8节介绍其解决
方案。
2.6 屏幕保护程序简单功能
代码改进 2.6.1 变量定义改进 上节实现的屏幕保护程序中总共定义了两种类型的四个变量 Boolean类型ReverseDirection、QuitFlag Byte类型 D1、 N1 它们都是定义在所有子程序之前是窗体变量。
分析一下使用这些变量的地方发现QuitFlag用于Timer1_Timer、Form_KeyDown和Form_MouseMove三个子程序中而ReverseDirection、D1和N1只用于Timer1_Timer这么一个子程序中说明它们的作用范围只在这个子程序内部与其它子程序无关这样的变量可以将其定义成某个子程序内部的静态变量。
Dim QuitFlag As Boolean Dim ReverseDirection As Boolean Dim D1 As Byte Dim N1 As Byte Private Sub Timer1_Timer Static ReverseDirection As Boolean Static D1 As Byte Static N1 As Byte N1 N1 1 上面
代码中以单引号开头的三行为注释相当于将它们删除了前面的单引号表示注释。
这样改进后的程序与前面程序的功能完全一致。
在Visual Basic的
代码窗口中各子程序的顺序与其执行顺序无关所有可以任意调整它们的位置。
为了说明变量定义的变化上述
代码中已经将子程序Timer1_Timer之前的几个子程序移动到它后面。
2.6.2 全屏显示功能改进 上节
代码中全屏幕显示功能是通过将Form1对象的WindowState属性设置成2实现的相当于运行时用鼠标点击窗口右上角的最大化按钮。
窗口Form1本身的大小仍然是设计时的大小。
由于Form1对象的大小用Width和Height表示只要知道.