《新编Visual-Basic程序设计教程》第14章_第1页
《新编Visual-Basic程序设计教程》第14章_第2页
《新编Visual-Basic程序设计教程》第14章_第3页
《新编Visual-Basic程序设计教程》第14章_第4页
《新编Visual-Basic程序设计教程》第14章_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第14章

操作Windows环境使用剪贴板激活其他Windows应用程序中断和后台处理14.1使用剪贴板GetText和SetText方法,用来传送文本。GetData和SetData方法,用来传送图形。Clear方法,可以处理文本和图形两种格式。在Windows环境中有一个特殊的对象,它是用来暂时保存文本和图形的;只要Windows操作系统在运行,我们随时都可以使用这个对象。这个对象就是我们现在要讲的剪贴板。VisualBasic中的Clipboard对象提供了访问系统资源剪贴板的方法。Clipboard对象用于操作剪贴板上的文本和图形,它使我们能够复制、剪切和粘贴应用程序中的文本和图形。Clipboard对象没有属性和事件,只有几个与环境剪贴板往返传送数据的方法。这些方法分别是:剪贴板中可以有多段数据,每段数据格式不同。比如,我们可以用SetData方法把一个图形的信息以位图格式存放到剪贴板中去,然后再用SetText方法把一串字符串存放到剪贴板中。接下来我们就可以用GetText方法来获得剪贴板中的字符文字信息,用GetData方法来获得剪贴板中的图形信息。14.1.1使用剪贴板处理文字在处理文字时,Clipboard对象使用的方法是SetText和GetText。我们可以使用这两个方法向Clipboard发送字符串数据和从Clipboard接收字符串数据,其操作过程如下图所示。用SetText和GetText方法向剪贴板和从剪贴板传送数据SetText方法将文本字符串数据发送到Clipboard上,替换先前存放在那里的文本。其语法如下所示:GetText方法的作用是返回当前存储在Clipboard内的字符串数据,我们也可以把它当作一个函数来使用。除了SetText和GetText两个方法外,我们在使用Clipboard对象进行文本处理时还经常会用到Clipboard对象的Clear方法,该方法的作用是清除已经存储在Clipboard内的文字或图形数据,其语法如下:了解了Clipboard对象以上三个方法后,我们就可以轻松的编写出类似于“记事本”应用程序的“复制”、“剪切”与“粘贴”等菜单命令。DimdataAsString:Clipboard.SetTextdataDimdestinationAsStringdestination=Clipboard.GetTextClipboard.Clear例14.1建立如下图所示的菜单应用程序,图中文本框Name属性为:Text1,分别以mnuCopy、mnuCut、mnuPaste和mnuClear为“编辑”菜单下的“复制”、“剪切”、“粘贴”和“清空剪贴板”四个子菜单命名。剪贴板应用演示程序编写以下代码,就可以实现上面提到的4个功能。Rem“复制”命令的实现PrivateSubmunCopy_Click()Clipboard.Clear '清空剪贴板中原有的数据Clipboard.SetTextText1.SelText '将文本框Text1内被选中的字符串发送到剪贴板EndSub

Rem“剪切”命令的实现PrivateSubmnuCut_Click()Clipboard.ClearClipboard.SetTextText1.SelTextText1.SelText="" '复制后删除文本框Text1内被选中的文字EndSubRem“粘贴”命令的实现PrivateSubmnuPaste_Click()Text1.SelText=Clipboard.GetText '把剪贴板内的文字信息发送到文本框当前位置EndSub

Rem“清空剪贴板”命令的实现PrivateSubmnuClear_Click()Clipboard.ClearEndSub14.1.2在剪贴板上使用图形格式Windows的剪贴板支持不同格式的几块数据同时存放在Clipboard上。其中,Clipboard的GetData和SetData方法允许处理图形数据格式。类似于SetText方法,SetData方法的作用是将记载图形信息的二进制数据发送到Clipboard上,替换先前存放在那里的相应格式的数据。其语法如下所示:同样,类似于GetText方法,GetData方法的作用是返回当前存储在Clipboard内的图形数据。我们也可以把它当作一个函数来使用,其语法如下:知道了Clipboard对象的以上两种方法后,我们就可以像复制字符串一样去复制图形数据。下面就以一个简单的图形复制程序为例,向大家介绍Clipboard对象的SetData与GetData两种方法的应用方式。Clipboard.SetDataPicture1.Picture'假定当前工程中有一图片框对象Picture1。Picture1.Picture=Clipboard.GetData()例14.2建立如下图所示的应用程序,图中左侧图片框Name属性为:Picture1,右侧图片框Name属性为:Picture2;标题为“剪切”的命令按钮的Name属性为:Command1,标题为“粘贴”的命令按钮的Name属性为:Command2,并且向图片框Picture1内添加一个图形。使用剪贴板处理图形数据演示程序编写以下代码,实现上面两个命令按钮的功能。PrivateSubForm_Load()Command1.Enabled=TrueCommand2.Enabled=False '程序运行时禁用粘贴命令以免发生逻辑错误EndSub

PrivateSubCommand1_Click()Clipboard.Clear'清除剪贴板内原有数据Clipboard.SetDataPicture1.Picture'将图片框Picture1的图像数据装入剪贴板Picture1.Picture=LoadPicture("")'清除图片框Picture1的图像Command1.Enabled=False'禁用剪切命令以免发生逻辑错误Command2.Enabled=True'启用粘贴命令EndSubPrivateSubCommand2_Click()Picture2.Picture=Clipboard.GetData'将剪贴板上的图形数据装入Picture2图片框MsgBox"图形剪贴板演示程序完成",vbOKOnly,"演示结束"EndEndSub在以上程序的注释语句中已经详细说明了使用Cilpboard对象处理图形数据的方法,望读者详细阅读。14.2激活其他Windows应用程序前面曾经提到过,Windows环境下的应用程序并不象DOS时代用C语言编制出的“程序孤岛”,而是Windows环境下的动态组成部分。因此,Windows环境下运行的应用程序在其自身运行时往往还需要激活其他应用程序,甚至还要能够发送一些键盘消息来控制其他应用程序的执行。因此,VisualBasic为我们提供了以下几种语句来完成上面提到的程序功能,其中包括:Shell、AppActivate和SendKeys三个函数(语句)。14.2.1使用Shell函数前面章节中曾经介绍过,VisualBasic可以定义和调用自己的程序过程。实际上,在VB中我们不仅可以调用通用过程,而且还可以调用其他的应用程序。这一功能是通过Shell函数实现的,其语法形式如下:Shell函数的语法解释如下:(1)X为一个Double类型变量,用来接收Shell函数的返回值。如果Shell函数成功的运行了指定的可执行程序,它将返回该程序的任务ID。任务ID是一个唯一的数值,用来标识驻留在内存中(既正在运行)的程序。如果Shell函数没用顺利打开指定的可执行程序,则会产生错误。(2)FilePath为必选参数,是字符串型的变量或常量,用来指定要执行的应用程序的文件名(包括文件路径),且该程序必须是可执行文件。也就是说,其扩展名称必须为.COM、.EXE、.BAT或.PIF,其他文件不能使用Shell函数对其调用。此外,我们还可以在FilePath参数中加上调用的应用程序的执行参数或命令行变量。X=Shell(FilePath[,WindowStyle])(3)WindowStyle为可选参数,是整型变量或常量,用来设定被调用的应用程序在运行时窗口的风格。若省略,被调用程序以具有焦点的最小化窗口来执行。WindowStyle参数的可选值与其对应的常量如下表所示。常量值描述vbHide0窗口被隐藏,且具有焦点vbNormalFocus1窗口呈正常大小显示,且具有焦点vbMinimizedNoFocus2窗口呈最小化显示,且具有焦点vbMaximizedFocus3窗口呈最大化显示,且具有焦点。vbNormalNoFocus4窗口不具有焦点,且呈正常大小显示vbMinimizedNoFocus6窗口不具有焦点,且呈最小化显示WindowStyle参数的可选值与其对应的常量例14.3

编写如图14-4所示程序,用Shell函数调用其他应用程序。此处假定该程序中包含有4个命令按钮对象Command1~Command4,它们的Caption属性分别为:“记事本程序”、“画笔程序”、“计算器程序”和“退出”。Shell函数演示程序编写以下代码,实现上面程序的各项功能。PrivateDeclareFunctionGetWindowsDirectoryLib"kernel32"_Alias"GetWindowsDirectoryA"(ByVallpBufferAsString,_ByValnSizeAsLong)AsLongRem以上代码的作用是声明一个API函数,该函数的作用是获取Windows目录的路径。

DimWinPathAsString,filePathAsStringPrivateSubForm_Load()DimxAsLongWinPath=Space$(200)x=GetWindowsDirectory(WinPath,200)WinPath=Left(WinPath,x)+"\"EndSubPrivateSubCommand1_Click()filePath=WinPath+"notepad.exe"ID1=Shell(filePath,vbNormalFocus)EndSub

PrivateSubCommand2_Click()filePath=WinPath+"Pbrush.exe"ID2=Shell(filePath,vbNormalFocus)EndSubPrivateSubCommand3_Click()filePath=WinPath+"Calc.exe"ID3=Shell(filePath,vbNormalFocus)EndSub

PrivateSubCommand4_Click()EndEndSub上面是窗体对象和命令按钮的事件过程。在窗体对象的Load事件过程中调用API函数(GetWindowsDirectory)得到当前Windows操作系统目录的路径,并将其保存在模块级变量WinPath内,然后在每个命令按钮的Click事件过程中,在WinPath变量后连接上连接上相应的应用程序的文件名,得到该应用程序完整的路径名称,并将其存放在变量filePath内,接着利用Shell函数去调用filePath变量指定的应用程序。14.2.2使用AppActivate语句使用AppActivate语句,可以将程序焦点从当前应用程序转移到Windows环境中正在运行的其他程序上。其语法如下:AppActivate语句的语法解释如下:(1)Title必选参数,数据类型为字符串型或Double型,字符串的内容是需要激活的应用程序窗口的标题。也可以使用Shell函数返回的Double型任务标识码来代替title字符串,以激活应用程序。(2)Wait可选参数,Boolean型,该参数是用来说明在激活另一个应用程序之前调用的应用程序是否有焦点。如果为False(默认值),那么即使调用的应用程序没有焦点,也直接激活指定的应用程序。如果为True,则调用的应用程序会到自己再次得到焦点后,才激活指定的应用程序。AppActivatetitle[,wait]下面几句代码简单说明了如何使用AppActivate语句。其中,例子中用到的Shell函数均假定被调用的应用程序已经存在于指定的路径中。DimIDAsLongAppActivate"MicrosoftWord"'激活Word应用程序。

'AppActivate语句也可以利用Shell函数的返回值作为参数,来激活应用程序。ID=Shell("c:\windows\notepad.exe",vbNormalNoFocus)AppActivateID14.2.3使用SendKeys语句向其他程序发送消息使用SendKeys语句,可将一个或多个按键消息发送到活动窗口,就如同有人从键盘上输入了这些消息一样,从而达到对其他应用程序进行信息输入或控制的目的。SendKeys语句的语法如下:SendKeys语句的语法具有以下两个命令参数,如下表所示。SendKeysMsgString[,wait]参数描述MsgString字符串型,为必选参数,指定要发送的按键消息Wait可选参数,用于指定等待的方式。如果为False(缺省值),则在按键消息发送出去之后立刻返回到过程。如果为True,则SendKeys语句会等接收消息的程序处理完上一个消息后,才发送第二个消息到指定程序去Sendkeys语句的参数说明:MsgString参数是由一个或多个字符组成的字符串,如果要发送单一的键盘信息,则该参数的字符串内容为该字符本身。例如,为了表示字母A,可用"A"作为MsgString。为了表示多个字符组成的键盘消息,就必须在前面的字符后面直接加上下一个字符。例如,要表示A、B及C,可用"ABC"作为MsgString参数。对SendKeys语句来说,加号“+”、插入符“^”、百分号“%”、上划线“~”及圆括号“()”都具有特殊意义。为了指定上述任何一个字符,都要将其放入大括号“{}”内。例如,要指定加号,可用“{+}”表示。同样为了使用大括号字符,也要使用“{{}”及“{}}”。为了发送那些不显示的字符到其他应用程序,例如Enter或Backspace等表示动做的而不是显示字符的按键,都要使用下表所列出的代码。按键动作代码按键动作代码Backspace{BACKSPACE}、{BS}或{BKSP}PageUp{PGUP}Break{BREAK}ScrollLock{SCROLLLOCK}CapsLock{CAPSLOCK}Tab{TAB}DelorDelete{DELETE}或{DEL}F1{F1}↓{DOWN}F2{F2}←{LEFT}F3{F3}↑{UP}F4{F4}→{RIGHT}F5{F5}End{END}F6{F6}Enter{ENTER}或{~}F7{F7}Esc{ESC}F8{F8}Help{HELP}F9{F9}Home{HOME}F10{F10}Insert{INSERT}F11{F11}NumLock{NUMLOCK}F12{F12}PageDown{PGDN}SendKeys语句中动作按键的代码熟悉Windows操作的读者都知道,我们在Windows环境下使用各种应用程序时都不免会使用功能键Shift、Ctrl及Alt等来辅助操作。因此SendKeys语句为了控制其他程序也需要能够发送这些功能键信息。这些功能的代码如下表所示。按

键代

码SHIFT+CTRL^ALT%功能键代码表为了说明使用SendKeys语句发送组合键的方法特对以下几句VB语句加以说明:除了以上功能SendKeys语句还可以将单个按键信息重复多次发送到指定的应用程序上去其形式为:{Keynumber}。使用时必须在Key与number之间加一个空格。例如:

下面给出两个例子来演示SendKeys语句的作用。SendKeys"+E"'代表发送按下Shift+E键SendKeys"^%P"'代表发送按下Ctrl+Alt+P键SendKeys"%{F4}"'代表发送Alt+F4键SendKeys"%(DF)"'代表发送按下Alt的同时还按下D键和F键SendKeys"%DF"'代表发送按下Alt的同时还按下D键,然后又按下F键SendKeys"{a20}"'发送20个a到指定程序。例14.4

如下图所示建立一个单窗体工程,向窗体Form1上添加一个Name属性为Command1,Caption属性为“演示SendKeys”的命令按钮。在Command1对象的单击事件中,使用Shell函数来运行微软Windows操作系统所附的记事本程序,然后使用SendKeys语句向被激活的记事本程序中发送指定的字符串信息。要求在记事本程序上显示字符串信息“HelloWorld!”,然后换一行显示20个由A组成的字符串。SendKeys演示程序一其程序如下。PrivateDeclareFunctionGetWindowsDirectoryLib"kernel32"_Alias"GetWindowsDirectoryA"(ByVallpBufferAsString,_ByValnSizeAsLong)AsLongRem以上代码的作用是声明一个API函数,该函数的作用是获取Windows目录的路径。

DimWinPathAsString,filePathAsStringPrivateSubForm_Load()DimxAsLongWinPath=Space$(200)x=GetWindowsDirectory(WinPath,200)WinPath=Left(WinPath,x)+"\"EndSubPrivateSubCommand1_Click()filePath=WinPath+"notepad.exe"ID1=Shell(filePath,vbNormalFocus)SendKeys"HelloWorld!!"SendKeys"{ENTER}"SendKeys"{A20}"EndSub其运行结果如下图所示。例14.4运行结果例14.5

建立如下图所示工程,在命令按钮对象的单击事件中,使用Shell函数来运行微软Windows操作系统所附的应用软件计算器本程序,然后使用SendKeys语句控制计算器去计算从1一直加到100的加法运算,要求得到计算结果。SendKeys演示程序二PrivateDeclareFunctionGetWindowsDirectoryLib"kernel32"_Alias"GetWindowsDirectoryA"(ByVallpBufferAsString,_ByValnSizeAsLong)AsLongRem以上代码的作用是声明一个API函数,该函数的作用是获取Windows目录的路径。DimWinPathAsString,filePathAsStringPrivateSubForm_Load()DimxAsLongWinPath=Space$(200)x=GetWindowsDirectory(WinPath,200)WinPath=Left(WinPath,x)+"\"EndSubPrivateSubCommand1_Click()filePath=WinPath+"Calc.exe"ID1=Shell(filePath,vbNormalFocus)SendKeys"%VS",True'将计算器程序转换到科学型计算器样式Fori=1To99SendKeysCStr(i)&"{+}",TrueNextiSendKeys"100=",TrueEndSub本程序运行结果如右图所示。例14.5运行结果14.3中断和后台处理什么是中断?简单地说,中断是一个“过程”。这一过程一般是由计算机的硬件或软件引起的,即CPU暂时中止现行程序的执行,转去执行其他程序,待处理完毕后又回到被中止了的程序这样一个过程。在Windows环境的操作过程中,与中断这一概念连接的最紧密的概念就是后台处理这种程序运行机制了。请读者试运行以下程序:例14.6PrivateSubForm_Click()DimxAsDoublePrintNow()x=1Fori=1To100000000'作1亿次浮点乘法运算x=i*3.1415926NextiPrintxPrintNow()EndSub该程序在窗体对象的单击事件中,进行了1亿次的浮点乘法运算。读者在运行该程序时会非常明显的感觉到,程序运行时的停顿。作者在CPU主频率1.8GHz的奔腾4上运行该程序的单击事件。总共消耗18秒左右的时间,其运行结果如下图所示。细心的读者会发现在程序运行到1亿次浮点乘法运算的停顿时我们将无法再对该程序进行操作,甚至无法用鼠标移动该窗体对象到其他位置。这是因为Windows是抢先式多任务操作系统,而例14.6程序中For循环语句所造成的1亿次浮点乘法运算,大量抢占了处理器的运算资源,从而造所了无法响应其他事件的结果。为了使程序在进行多次循环,大时间片运算时还能正常响应其他事件,在VisualBasic编程技术中有使用定时器控件和DoEvents()语句两种常用技巧。例14.6运行结果14.3.1使用定时器控件进行后台处理在前面章节中我们已经掌握了如何使用定时器控件。只是还没有掌握使用它进行后台程序处理的思想,本节中就一起来讨论如何运用这种技巧。把后台任务代码放入Timer事件中,用全局、模块或静态变量存储Timer事件过程中必须一直保存的变量。当Timer事件获得控制权后,使其运行事件时间稍大于Interval属性指定的时间,这将确保后台任务能够充分利用系统分配的时间片。为定时器控件的Interval属性设置较大的值,这将使处理更为有效。充分抢先式多任务操作系统的特点,能够防止其他应用程序被阻塞。而且在取消长时间任务时,用户通常也能够容忍短暂的延迟。如果在编制多线程任务时,最好能以定时器控件的Enabled属性为标志,防止其他线程再次启动已经运行的后台任务。例14.7

建立图一个单窗体工程,向工程中添加一个定时器控件(Timer1)和一个图像框控件(Image1),然后在代码窗口中编写以下程序,DimNowXAsInteger'定义窗体模块变量NowX

PrivateSubForm_Load()Timer1.Interval=65'App.Path系统变量,用来记载当前程序所在路径名称m=App.Path&"\1.jpg"Image1.Picture=LoadPicture(m)Image1.Top=0Image1.Left=0Form1.Width=Image1.WidthEndSubPrivateSubTimer1_Timer()Image1.MoveImage1.Left,Image1.Top-30IfImage1.Top+Image1.Height<=Form1.HeightThenNowX=NowX+1'NowX窗体模块级变量用来保存下一个将被'显示的图片的主文件名m=App.Path&"\"&CStr(NowX)&".jpg"Image1.Picture=LoadPicture(m)Form1.Width=Image1.WidthImage1.RefreshImage1.Top=0IfNowX>=4ThenNowX=0EndIfEndSub本程序运行时,要保证程序文件所在目录内有4个图形文件,文件名分别为1.jpg、2.jpg、3.jpg和4.jpg,并且每个图片的高度都要大于本程序中窗体对象的高度。在以上条件被满足时运行该程序会实现这样的程序功能:在一定的时间间隔,图形向上移动,当一个图形的全部内容都被显示后,再换下一个图形。当4个图形都显示完以后,再从1.jpg图片重新显示。在本程序运行时,我们可以使用鼠标拖拽该程序窗口进行移动。这代表操作系统除了本程序中响应定时器对象的Timer事件外,还可以响应其他操作。也就是说,系统中其他程序没有因为运行当前程序而被阻塞。从而达到了进行后台操作的目的。14.3.2使用DoEvents语句进行后台处理尽管定时器控件是进行后台处理很好的工具,但是我们还有更加专业一些的方法,那就是DoEvents语句。VisualBasic中DoEvents语句的作用是暂时把控制权交还给Windows操作系统,以便让操作系统处理其他事件。DoEvents语句的语法如下:DoEvents让我们对例14.6进行一些改变,得到以下程序:例14.8PrivateSubForm_Click()DimxAsDoublePrintNow()x=1Fori=1To1000000'作100万次浮点乘法运算x=i*3.1415926DoEvents'把控制权交还给操作系统,允许系统响应其他事件。NextiPrintxPrintNow()EndSub前面章节中我们看到了,当例14.6程序运行时,我们甚至不能用鼠标移动其窗体对象到其他位置。但是在我们向例14.6程序的For循环语句中加上了DoEvents语句后,在该程序运行时我们就可以用鼠标移动其窗体对象。这是因为DoEvents语句把控制权交还给操作系统,允许Windows系统响应其他事件。因此,我们用鼠标移动其窗体对象的操作自然会被响应。可是细心的读者会发现,为什么要把例14.6程序中1亿次循环浮点乘法运算,给变成例14.8程序中100万次循环浮点乘法运算呢?其实在我们看完其运算结果后,这个疑问自然会被解开的。下图显示了作者的电脑运行例14.8的结果。我们会发现,在For循环中加上了DoEvents语句后,进行100万次浮点乘法运算居然需要8秒钟的时间。而如果去掉DoEvents语句,如例14.6程序运行结果,进行1亿次浮点乘法运算所消毫的时间也只有18秒左右。这也说明了,虽然DoEvents语句允许操作系统响应其他事件的操作,但是这是以大量消耗程序运行速度为代价的。运行结果因此在读者使用DoEvents语句时,一定要慎重考虑在你的程序中使用它是否合适,会不会大规模的降低我们程序的处理效率。那么有没有一种比较折中的办法,让程序既能响应操作系统的其他操作,同时又能够以较高的效率来进行后台处理,回答当然是肯定的。其实这只是一种编程的技巧,我们可以把例14.6作进一步的改变。其改变后的程序代码如例14.9所示。例14.9PrivateSubForm_Click()DimxAsDoublePrintNow()x=1Forj=1To1000'外循环总共循环了1000次Fori=1To100000'每次内部循环执行10万次浮点乘法运算x=i*3.1415926NextIDoEvents'把控制权交还给操作系统,允许系统响应其他事件。Nextj'最终我们共执行了1亿次浮点乘法运算PrintxPrintNow()EndSub该程序运行结果如下图所示。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论