




已阅读5页,还剩26页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
屏幕保护程序设计屏幕保护程序简单功能实现2.5.1 文字单向移动功能实现本屏幕保护程序的主体功能是文字在屏幕左右移动,首先需要在屏幕上显示文字。对于Visual Basic程序而言,在屏幕上显示文字,实际上是显示在某个窗口上。显示文字可以采用两种方法:第一种方法是直接在窗口某个位置输出文字,这种方法需要调用某个函数或窗口对象的方法并指定坐标,如果改变其位置,则需要在新位置重新输出文字,并且将原来位置的文字擦除,这种文字输出在设计时看不到效果,只有运行程序时才能看到效果;第二种方法是采用某个对象显示文字,文字的移动仅仅需要改变该对象的位置即可,并且在设计时就能够看到效果。这里采用第二种方法显示文字,即采用前面介绍的标签对象显示文字。创建一个新的Visual Basic工程,系统自动创建一个窗口对象Form1,并显示Form1的对象设计窗口。向窗口Form1上拖放一个标签对象,系统自动命名为Label1(最后一个字符为数字1,倒数第二个字符为小写字母l 。Visual Basic集成开发环境自动以数字后缀对新创建的控件对象命名,对下一个标签命名为Label2),选中该对象,定位到属性窗口,修改Label1对象的属性:l Caption :欢迎使用Visual Basicl 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,需要进入代码窗口,方法有三个:l 选择工程资源管理器窗口上方最左侧图标(View Code)l 选择“View”菜单下“Code”子菜单l 双击Form1的对象设计窗口在代码窗口上方的两个组合框中,分别选择对象Label1和事件Click,则自动产生该子程序的框架。由于Click事件是标签对象的默认事件,只要选择了Label1,就会自动产生该子程序框架。另外,如果在对象设计窗口中直接双击Label1对象,进入代码窗口后自动产生该子程序框架。定位到子程序框架内部,输入代码如下:Private Sub Label1_Click() Label1.Left = Label1.Left + 100End Sub这句代码的含义是每次点击Label1对象,其Left属性在原有基础上增加100,实际效果就是向右移动100,单位就是前面介绍的Twip(1/1440英寸)。选择“Run”菜单下的“Start”子菜单或直接点击工具栏上的小图标,运行该程序。图2.5即为运行开始以及单击文字几次以后的文字位置。 图2.5 标签Label1的运行效果如果能够在某个特定的时间内自动执行上面这样的子程序,就可以实现文字的自动移动。Visual Basic提供的定时器对象可以实现这样的功能。切换到对象设计窗口,有两种方法:l 选择工程资源管理器窗口上方中间图标(View Object)l 选择“View”菜单下“Object”子菜单向窗口Form1上拖放一个定时器控件,自动命名为Timer1,修改其属性:l Interval:100l Enabled:True双击Timer1对象,进入代码窗口并自动产生子程序框架Timer1_Timer,将Label1_Click子程序中的代码拷贝到子程序Timer1_Timer中。Private Sub Timer1_Timer() Label1.Left = Label1.Left + 100End Sub重新运行该程序,则文字会自动向右移动,如果需要改变文字移动的速度,可以改变Timer1对象的Interval,也可以修改上述代码中的移动量100。对于上面的两个子程序,都是由系统在接收到相应事件后自动调用的,程序员自己编写的代码中并没有调用它们的地方。这样的事件处理子程序除了由系统自动调用外,也可以由程序员指定调用。例如,上述两个子程序的内容实际是一致的,没有必要重复写两次,完全可以由一个子程序调用另外一个子程序,将上述程序修改如下:Private Sub Label1_Click() Timer1_TimerEnd Sub在子程序Label1_Click中调用子程序Timer1_Timer。程序运行效果与前面程序一致。由于在定时器内实现文字移动,人工移动的子程序Label1_Click实际上已经没有用了,完全可以删除掉。如果不删除该子程序,则既可以自动移动,也可以人工移动。2.5.2 文字双向移动功能实现到目前为止,实现了文字的自动移动,但当文字移动到窗口最右侧后,看不到文字了,需要将其反向,向左移动。从前面程序已知,向右移动是Label1的Left属性每次加上一个数值(100),向左移动则应该是Label1的Left属性每次减去一个数值(100)。那什么时候该减呢?应该是在文字的最右端碰上窗口的右边框时,为此需要判断文字是否超出窗口右边框。标签Label1只有Left属性而没有Right属性,但其提供了Width属性,Left属性加上Width属性就是Label1对象的最右侧(Label1.Left+Label1.Width)。前面已经介绍过,窗口对象Form1的宽度采用Width属性表示,但文字是在其客户区内移动,这里需要采用其ScaleWidth属性。在子程序Timer1_Timer内采用If语句比较Label1.Left+Label1.Width与Form1.ScaleWidth,形式如下:If Label1.Left + Label1.Width = Form1.ScaleWidth Then End If标签Label1的Left属性每次减100的代码应该写在哪里?很多人的第一感觉就是写在上面的这个条件语句内,如下所示:Private Sub Timer1_Timer() Label1.Left = Label1.Left + 100 If Label1.Left + Label1.Width = Form1.ScaleWidth Then Label1.Left = Label1.Left - 100 End IfEnd 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 BooleanPrivate Sub Timer1_Timer() If ReverseDirection = False Then Label1.Left = Label1.Left + 100 If Label1.Left + Label1.Width = Form1.ScaleWidth Then ReverseDirection = True End If Else Label1.Left = Label1.Left - 100 If Label1.Left = Form1.ScaleWidth Then ReverseDirection = True End If Else Label1.Left = Label1.Left - 100 If Label1.Left 50 Then D1 = 1 Else Label1.FontSize = Label1.FontSize - 2 If Label1.FontSize 10 Then D1 = 0 End If Label1.ForeColor = RGB(255 * Rnd, 255 * Rnd, 255 * Rnd)End Sub图2.6所示为简单屏幕保护程序运行过程中文字变化的截图。图2.6 文字动态变化效果图2.5.4屏幕保护程序结束功能实现普通窗口可以通过标题栏上的关闭按钮结束程序,而屏幕保护程序运行时没有标题栏,也就不能点击关闭按钮。Visual Basic提供了一个结束应用程序的语句End。在需要结束屏幕保护程序的子程序中调用End语句即可。屏幕保护程序一般是在移动鼠标或按键时结束。为此,需要对窗口对象Form1的KeyDown事件和MouseMove事件进行处理,编写如下的子程序。Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) EndEnd SubPrivate Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) EndEnd Sub比较上面代码中子程序名称代码与前面子程序名称的区别,对Label1和Timer1对象,其事件处理子程序名称由对象名称_事件名称组成,如Label1_Click和Timer1_Timer,而窗口处理子程序名称则由Form_事件名称组成,这是因为在某个窗口内,只有一个Form类型的对象(代表窗口本身),不需要再用类似于Form1或Form2这样的名称加以区分。这种命名方式只适用于事件处理子程序,在某个子程序内部使用窗口对象时,仍然采用具体的Form1、Form2这样的名称,其原因是在某个窗口内部的子程序中可以使用其它窗口对象的属性、方法。添加上述代码以后,在Visual Basic集成开发环境中使用鼠标选择菜单或工具栏图标运行程序,发现程序刚一开始运行就自动结束了。发生这个现象的原因在于:用鼠标选择菜单或图标时,不可能保证鼠标一点都不动,也就是说肯定会产生鼠标移动事件,从而使得屏幕保护程序一运行就接收到MouseMove事件,系统自动调用上述的Form_MouseMove子程序,结束程序。为了解决这个问题,可以采用两种方法:l 记录两次MouseMove的移动距离,如果大于某个值就结束程序。l 延时一段时间后再根据鼠标或键盘事件结束程序。这里采用第二种方法。窗口Form1中已经有了一个定时器Timer1,它每隔100毫秒发生一次Timer事件,可以记录发生Timer事件的次数产生需要的延时。为了保证屏幕保护程序能够运行起来,设置5秒的延时,需要记录50次Timer事件,可以定义一个Byte类型的变量保存Timer事件的次数。由于需要延时一段时间才可以接收鼠标或键盘事件程序结束,还需要定义一个Boolean类型变量表示是否可以结束。Dim ReverseDirection As BooleanDim D1 As ByteDim QuitFlag As BooleanDim N1 As BytePrivate Sub Form_KeyDown(KeyCode 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其中的N1=0这条语句必须有,否则每次发生Timer事件都计数,当变量N1的值超过其表示范围时就会出错(对于Byte类型的变量,超过255就出错),也就是说,程序运行25.5秒后就会弹出如图2.7所示的提示窗口。图2.7 变量N1超过255产生的出错提示点击上图的“Debug”按钮,进入代码窗口,以黄色标记出错的语句N1=N1+1,将鼠标光标放到变量N1上,提示当前N1的值已经是255,希望将N1再加1时超过Byte类型变量的表示范围,如下所示:继续运行仍然会弹出图2.7所示窗口,只能选择“End”结束。2.5.5屏幕保护程序基本功能完善上面的程序实际上仅仅是一个简单的Windows程序,屏幕保护程序运行时往往具有如下特征:占据整个屏幕;黑色背景;没有标题栏。这些功能都可以通过Form对象的属性解决,为此,对Form1对象和Label1对象设置如表2.6所示的属性。表2.6 Form1和Label1对象的主要属性设置对象属性值含义Form1BackColor黑色窗口背景为黑色BorderStyle0没有边框和标题栏WindowState2窗口运行时最大化,占据整个屏幕Label1BackStyle0标签背景透明,与窗口颜色一致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 变量定义改进上节实现的屏幕保护程序中,总共定义了两种类型的四个变量:l Boolean类型:ReverseDirection、QuitFlag l Byte类型: D1、 N1它们都是定义在所有子程序之前,是窗体变量。分析一下使用这些变量的地方,发现:QuitFlag用于Timer1_Timer、Form_KeyDown和Form_MouseMove三个子程序中,而ReverseDirection、D1和N1只用于Timer1_Timer这么一个子程序中,说明它们的作用范围只在这个子程序内部,与其它子程序无关,这样的变量可以将其定义成某个子程序内部的静态变量。Dim QuitFlag As BooleanDim ReverseDirection As BooleanDim D1 As ByteDim N1 As BytePrivate 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表示,只要知道整个屏幕(实际是桌面)的大小,就可以将Form1的Width和Height设置成和屏幕宽度、高度一致,从而实现全屏幕显示。2.3.8节介绍的Screen对象就代表屏幕,只要将Form1的Width和Height设置成Screen对象的Width和Height属性即可。何时改变Form1对象的高度和宽度合适呢?2.3.2节介绍窗口对象时已经提到其Load事件,它是在准备绘制窗口前触发的事件,往往用于初始化。在这里改变Form1的Width和Height属性,Windows系统就会按照新的属性值绘制并显示窗口。在窗口的Load事件中,除了要改变Form1的Width和Height属性外,还需要将窗口Form1定位到整个屏幕的左上角,设置Form1对象的Left和Top属性为0。采用这种方法后,将Form1对象的WindowState属性重新设置为0,使其正常显示。Private Sub Form_Load() Randomize Me.Left = 0 Me.Top = 0 Me.Height = Screen.Height Me.Width = Screen.WidthEnd Sub2.7定制屏幕保护程序的密码校验窗口Windows屏幕保护系统自身具有密码校验功能。为了介绍文本框等控件的使用,本节定制一个密码校验窗口,与Windows屏幕保护系统自身的密码校验功能无关。 2.7.1 创建密码校验窗口密码校验采用一个独立的窗口实现。本程序目前只要一个窗口对象Form1,需要添加一个新的窗口对象,选择“Project”菜单的“New Form”子菜单,创建一个新窗口Form2,将其调整成合适的大小,并依照表2.7设置Form2对象的有关属性。表2.7 Form2对象的有关属性设置对象属性值含义Form2BorderStyle 1不可以调整窗口大小Caption密码校验窗口标题Font宋体,小四随后添加对象的默认字体StartUpPosition2窗口在屏幕上居中显示向Form2上拖放几个控件,形成图2.16(a)所示的画面。其中对象Label1和Text1必须拖放到对象Frame1上。再按照表2.8设置各个控件的属性,设置属性后的界面如图2.16(b)所示。表2.8 密码校验窗口有关控件属性设置对象属性值含义Frame1Caption 密码输入Label1Caption请输入密码提示信息Text1Text删除成空白开始时密码输入框内没有内容PasswordChar*以*号隐藏输入密码MaxLength6文字输入最大字符数量Command1Caption确定进行密码校验DefaultTrue响应回车键Command2Caption取消取消密码校验CancelTrue响应ESC键 (a)设置属性前 (b)设置属性后图2.16 密码校验窗口界面保存工程,提示如图2.9所示画面,将Form2.frm改成CheckPass.frm,再点击“保存”按钮。2.7.2 密码校验代码实现对于图2.16的密码校验窗口,用户从文本框Text1中输入密码,回车或点击“确定”按钮进行密码校验。由于将Command1的Default属性设置成True,回车动作与Command1的单击事件联系在一起,因而代码中只需要处理Command1对象的单击事件(Click)。在Form2的对象设计窗口中双击图2.16(b)中的“确定”按钮,进入Form2的代码设计窗口,系统自动创建了Command1_Click子程序,在其中添加判断文本框Text1的Text属性与预先设定密码是否相同的代码即可,如果相同则结束程序。Private Sub Command1_Click() If Text1.Text = 1234 Then EndEnd Sub文本框中输入的内容为字符串,即使是形似1234这样的数字,也是作为字符串处理的,所以比较时在1234其后加上了英文的双引号。上述代码仅仅实现密码正确时结束程序的功能,如果密码输入不正确,应该清除原先输入内容,让用户重新输入,为了避免无限次试密码,还应该限定密码输入的次数,为此,需要定义一个变量记录校验密码的次数,当密码输入次数超过设定次数后,卸载或隐藏密码校验窗口。卸载校验窗口,可以采用2.2.5节介绍的Unload语句,其格式为Unoad Form2或 Unload Me。隐藏密码校验窗口,采用2.3.2节介绍的窗口对象的Hide方法,其格式为Form2.Hide或Me.Hide。Dim T1 As BytePrivate Sub Command1_Click() If Text1.Text = 1234 Then End Else Text1.Text = T1 = T1 + 1 If T1 = 3 Then T1 = 0 Me.Hide End If End IfEnd Sub修改后的密码校验代码如上,其中变量T1定义在子程序之前,为窗体变量,用于记录密码输入次数,在子程序Command1_Click中,当次数等于3时,使用Me.Hide隐藏密码校验窗口,为了使下次校验密码时仍然只允许输错3次,需要将变量T1重新赋值为0。如果运行程序,仍然显示原来的Form1。这是因为当前工程中存在两个窗口对象Form1和Form2,而程序启动时只能显示其中的一个,系统默认选择第一个创建的窗口对象Form1作为启动窗口。如果希望单独调试Form2,即希望将Form2设置成启动窗口,选择“Project”菜单的“Project1 Properties”子菜单,弹出如图2.17所示的工程属性修改窗口,从“Startup Object:”下方的组合框中选择Form2。图2.17 启动窗口的改变单独调试完Form2后,还应该再次进入上图所示窗口,将启动对象改成Form1。重新运行程序,弹出如图2.18所示的密码校验窗口,用户输入的密码以*显示,如果输入1234回车,则结束程序,如果输入其它内容回车后,自动清空输入框,三次输入不正确后,密码校验窗口不见了,但程序并没有结束(使用Me.Hide将窗口隐藏起来了),而且再也不能显示密码校验窗口,只有通过Visual Basic集成开发环境“Run”菜单下的“End”子菜单或工具栏中的图标结束程序。如果将上面代码中的Me.Hide改成Unload Me,则三次输入不正确后,卸载窗口Form2,由于程序当前只有一个窗口显示,其效果也是结束程序。图2.18 运行时的密码校验窗口“取消”按钮对应的功能就是隐藏或卸载窗口Form2,可以使用Me.Hide或Unload Me实现。Private Sub Command2_Click() Unload MeEnd Sub2.7.3 限制密码输入框输入内容以上代码采用文本框Text1输入密码,其中可以输入各种字符,包括:数字、大小写字母以及各种符号。对于上面的校验密码1234,希望将文本框Text1的输入内容限制为仅仅能够输入数字,而不能输入字母和其它符号,即对Text1的输入内容进行过滤,将除数字外的其它符号过滤掉。2.3.4节介绍文本框对象时已经提到,每次输入一个字符,文本框对象都会触发一次KeyPress事件,并将输入字符的编码(ASCII码)作为参数一起送过来。本节就是对该事件进行处理。为了过滤Text1对象的输入字符,必须了解字符的编码,现在的目的是保留0到9的字符,也就是要判断输入字符的编码是否在“0”到“9”字符对应的编码范围内。由ASCII码表知道,字符“0”的ASCII码为48,字符“9”的ASCII码为57。如果不清楚字符的ASCII码,也可以使用2.4.3节介绍的ASC函数获取某个字符的编码,如获取字符“0”的ASCII码采用ASC(0)。进入Form2的代码窗口,从左上角组合框中选择对象“Text1”,系统自动产生一个子程序Text1_Change,这个子程序对应文本框对象的Change事件,只要文本框内容发生变化(输入或赋值),就产生这个事件,本节程序要求的是输入引起的事件,即需要处理KeyPress事件。将光标停留在子程序Text1_Change内,从右上角组合框中选择事件“KeyPress”,系统自动创建子程序Text1_KeyPress。对于原来自动创建的Text1_Change子程序,可以人工删除它,也可以保留它。只要运行一次程序后,系统自动删除所有没有任何内容的子程序。在新创建的子程序中对参数KeyAscii进行判断,只要不在48和57之间,就将该参数赋值为0,取消当前输入的字符,代码如下:Private Sub Text1_KeyPress(KeyAscii As Integer) If KeyAscii 57 Then KeyAscii = 0 End IfEnd Sub添加以上代码后,重新运行程序,图2.18的文本框中只能输入0到9的字符,输入的其它字符都没有显示到文本框中。如果在密码输入框中输错一个字符,希望将该字符删除再重新输入,大多数人往往采用键盘的“Back Space”键删除(该键实际是退格键,即删除当前光标前的字符),但添加上述代码后,退格键无效(用Del键仍然可以删除)。其原因在于:当用户按键盘的“Back Space”键时,产生一个ASCII编码为8的字符代表退格,这个字符同样触发KeyPress事件,而上述代码对编码在48到57之外的所有键均实施了屏蔽过滤,从而导致退格键无效。为了解决这个问题,需要在Text1_KeyPress子程序中单独对参数KeyAscii是否等于8进行处理,即只有编码在48到57之外并且不为8时才取消该字符。修改后的代码如下。Private Sub Text1_KeyPress(KeyAscii As Integer) If KeyAscii 57 Then If KeyAscii 8 Then KeyAscii = 0 End IfEnd Sub在文本框的KeyPress中除了可以处理退格键外,还可以分析处理回车键(KeyAScii=13)、ESC键(KeyAscii=27)等,采用这种方法,完全可以替代前面采用命令按钮Command1和Command2实现的密码判断以及取消功能。但必须先将Command1对象的Default属性和Command2对象的Cancel属性设置为False或将Command1和Command2对象删除。改进后的代码如下,与前面代码的功能完全相同。Dim T1 As BytePrivate Sub Text1_KeyPress(KeyAscii As Integer) If KeyAscii = 13 Then If Text1.Text = 1234 Then End Else Text1.Text = T1 = T1 + 1 If T1 = 3 Then T1 = 0 Me.Hide End If End If End If If KeyAscii = 27 Then Unload Me If KeyAscii 57 Then If KeyAscii 8 Then KeyAscii = 0 End IfEnd Sub如果删除了Command1和Command2对象,与其对应的Command2_Click和Command1_Click子程序可以删除,也可以保留,但它们不再是某个对象的事件处理子程序,而是普通的子程序,仍然可以由其它子程序调用。2.7.4 关联屏幕保护程序与密码校验窗口窗口Form1和Form2分别实现了屏幕保护程序主画面功能和密码校验功能,但这两个窗口之间没有任何联系,系统要么运行Form1,要么运行Form2。对于屏幕保护程序而言,应该以Form1实现的主画面作为启动窗口,当满足结束条件时,弹出Form2实现的密码校验窗口,如果密码校验成功,则结束整个屏幕保护程序,否则继续显示屏幕保护程序主画面。为了实现这个目的,需要对2.5.4节实现的程序结束功能进行修改,将Form1的子程序Form_KeyDown和Form_MouseMove中结束程序的语句替换成显示Form2的语句。显示窗口Form2可以利用2.3.2节介绍的窗口对象的Show方法实现,即用Form2.Show代替原来的End。通过工程资源管理器,切换到Form1的代码窗口,将子程序Form_KeyDown和Form_MouseMove的内容修改成如下格式:Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) If QuitFlag = True Then Form2.ShowEnd Sub再次选择“Project”菜单的“Project1 Properties”子菜单进入图2.17所示的工程属性修改窗口,将启动对象改成Form1。重新运行程序,启动文字动态显示的主画面,5秒后移动鼠标或按键,弹出图2.18所示密码校验窗口,如果输入1234则结束整个屏幕保护程序,如果不是输入1234,则清空输入框以重新输入,但奇怪的是,错误密码输入的次数不再仅仅为3次,而是没有限制,而Form2中的代码确实是3次后卸载Form2本身,应该回到Form1。实际上,这是一个不断地卸载Form2又加载Form2的过程。当在Form2中输入错误按回车键卸载Form2后,Form1同时也产生了KeyDown事件,而当时的QuitFlag变量等于True,又满足了弹出Form2的条件,为了解决这个问题,将Form1的Form_KeyDown和Form_MouseMove子程序修改如下:Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) If QuitFlag = True Then QuitFlag = False Form2.Show End IfEnd Sub为了保证两次密码校验间隔在5秒以上,还应该在上述代码中Form2.Show之前加上一行代码N1=0,前提是在2.6.1节中不要将变量N1重新定义成静态变量,这样就可以在Timer1_Timer中重新记录50次,使得QuitFlag再次变成True。2.8屏幕保护程序功能提高以上几节建立的Visual Basic程序能够实现简单的屏幕保护程序功能,但还存在以下几个问题:l 屏幕保护程序运行过程中仍然显示鼠标的光标,应该将其隐藏起来。l 由Windows系统启动屏幕保护程序时,起始画面不能正常显示(图2.14)。l Windows系统运行屏幕保护程序时,除了在指定时间内不动作鼠标和键盘外,还有参数设置和预览功能,对应图2.13中的“设置”和“预览”按钮,前面的程序没有实现这些功能。这些功能的实现除了应用Visual Basic的基本语法和对象外,还需要借助API函数的调用。2.8.1 API函数初步第一章已经介绍过API函数的基本概念,它是Windows系统提供给程序员编程使用的一系列函数,Windows系统下的任何一种编程语言都可以使用这些函数。一个优秀的Visual Basic程序,往往离不开对API函数的调用。Visual Basic6.0中如果需要使用API函数,必须采用Declared语句对其进行申明,即说明其函数名称以及调用格式等。API函数申明的格式如下:Public|Private Declare Function 函数名 Lib 库名 Alias 别名(参数表)As 类型Public|Private Declare Sub 函数名 Lib 库名称 Alias 别名(参数表)各个部分的含义如下:l Public| Private:表示该函数是公用函数还是私有函数,如果采用Public申明,则是公用函数,当前工程中的所有窗口都可以使用,如果采用Private申明,则为私有函数,只有申明该函数的窗口可以使
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 工程总承包意向协议书4篇
- 涂料购销合同模板常用版2篇
- 脚手架设计及计算
- 健康促进区县课件
- 2025西昌民族幼儿师范高等专科学校辅导员考试试题及答案
- 2025西安城市建设职业学院辅导员考试试题及答案
- 2025贵州装备制造职业学院辅导员考试试题及答案
- 2025皖南医学院辅导员考试试题及答案
- 2025绍兴文理学院辅导员考试试题及答案
- 设计企业核心竞争力构建路径
- 国开电大《职业素质(职业素质专)》形考1答案
- 过敏性休克的急救及处理流程教材课件(28张)
- 交通协管员劳务外包服务方案
- 顶管工程顶进记录表
- 沪教牛津版七年级上册英语全册教案
- 先天性心脏病患儿护理查房
- 2022年山东省威海市中考数学试题及答案解析
- (完整版)农业主要知识点
- 高级财务管理试题及答案
- 医院宁群脑高灌注综合症监测和防治
- T∕CSEA 1-2018 锌铝涂层 技术条件
评论
0/150
提交评论