精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>● VB和Basic>>〓〓..技术文章连载..〓〓>>走近编程通过实例学VB>>走近编程通过实例学VB(四)

主题:走近编程通过实例学VB(四)
发信人: chenjz(不再哭傲江湖)
整理人: cobe(2001-01-19 09:20:28), 站内信件
走近编程通过实例学VB(四) 
 


 
     在这一章的教程内,我们将完成编辑菜单中的各种功能。
    由于编辑菜单中的撤消键入和重复键入涉及到Windows API函数,这两个功能的实现我们将在后面的部分讲。首先介绍菜单中“全选、复制、剪切和粘贴”的实现。
    这些功能的实现比较简单,打开MDIForm1的代码窗口,在mEditCopy的Click事件中加入以下代码:
    If Me.ActiveForm.RichTextBox1.SelText<>"" Then
    Clipboard.SetText Me.ActiveForm.RichTextBox1.SelText,vbCFText
    End If
    在mEditCut的Click事件中加入以下代码:
    If Me.ActiveForm.RichTextBox1.SelText<>"" Then
    Clipboard.SetText Me.ActiveForm.RichTextBox1.SelText,vbCFText
    Me.ActiveForm.RichTextBox1.SelText=""
    End If
    在mEditPaste的Click事件中加入以下代码:
    Me.ActiveForm.RichTextBox1.SelText=Clipboard.GetText
    在mEditSelAll的Click事件中加入以下代码:
    Me.ActiveForm.RichTextBox1.SelStart=0
    Me.ActiveForm.RichTextBox1.SelLength=
    enB(Me.ActiveForm.RichTextBox1.Text)
    运行程序,在编辑窗口中键入内容,然后在菜单中选择全选、剪切等操作看一下程序的运行效果。
    在上面的程序中,SelStart属性指定RTF控件中被选中文本的起始位置,第一个字符的起始位置为0。如果没有文本选中,SelStart属性指出插入点(就是RTF控件中一闪一闪的I形光标位置)的位置。SelLength指定被选中文本的长度。如果没有文本选中,SelLength为0。通过设置这两个值可以选择RTF控件中的文本。而SelText属性返回或设置被选中的文本,如果没有文本被选中,则为零长度字符串。在上面的程序中,又出现了一个新的对象:Clipboard。这是VB提供的访问剪贴版的对象。Clipboard对象提供了以下的方法操控剪贴版:
    Clear方法:该方法清除剪贴版中的内容。
    GetFormat方法:返回一个整数,指出 Clipboard 对象中的项目是否匹配期望的格式。
    例如:x=Clipboard.GetFormat(vbCFText),如果剪贴版中的内容为文本类型,x就为非0值,否则为0。
    GetText、SetText方法:分别设置剪贴版中的文本以及获取剪贴版中的文本。如果剪贴版中的内容不是文本类型的,则GetText方法返回零长度字符串。
    接下来考虑实现菜单中的查找和查找下一个功能,我们可以通过UltraEdit的查找功能来看一下。当用户选择菜单中的查找项时,首先需要弹出查找对话框让用户输入需要查找的内容,然后当用户选择确定之后。对话框消失,同时当前编辑窗口从当前光标位置开始第一个符合查找条件的字符串被高亮显示。然后按F3键可以从当前位置继续查找。而且无论怎样切换编辑窗口,再回到原来的编辑窗口时按F3键还是可以从光标位置开始查找定义的查找字符串,也就是说,每一个编辑窗口可以“记住”查找字符串。很显然,这需要为Form1对象添加一个属性来保存在该窗口中的查找字符串。打开Form1的编辑窗口,在“通用”域添加如下代码:
    Dim strFind As String
    Property Get FindStr() As String
    FindStr=strFind
    End Property
    Property Let FindStr(sFind As String)
    strFind=sFind
    End Property
    这样就为Form1添加了一个FindStr属性,外部函数可以通过该属性获取和设置编辑窗体的查找字符串。
    接下来就是建立查找窗口,点击VB菜单的“Project|Add Form”项,选择Form,再选择打开添加一个普通窗体到工程中,将窗体的BorderStyle属性设置为3,Name属性设置为frmFind,然后添加一个TextBox控件到frmFind用于输入查找字符串,将该控件的Name属性设置为txtFind。添加两个CommandButton控件,一个查找按钮,一个取消查找按钮。将查找按钮的Caption属性设置为查找,将Name属性设置为cmdFind。将取消查找按钮的Caption属性设置为取消,Name属性设置为cmdCancel。同时为了增加操作的方便性,将cmdFind的Default属性设置为True,将cmdCancel的Cancel属性设置为True。CommandButton控件的Default属性定义一个按钮是否为缺省按钮,如果为True,则该按钮就被设置为缺省按钮,当用户在窗口中按回车键时,就会引发缺省按钮的Click事件。而Cancel属性定义一个按钮是否为取消按钮,当一个按钮是取消按钮时,在窗体处于活动状态时,按Esc键将引发该按钮的Click事件。设计好的窗体如图1所示,点击菜单“File|Save frmFind.frm”保存窗体。
    下面我们要实现的是:点击查找按钮后弹出查找对话框,然后当在对话框中输入查找字符串后,在编辑窗口当前插入点位置后开始查找,将找到的第一个字符串高亮显示,然后当用户按F3查找下一个内容时,从高亮显示的位置开始向下查找。
    首先我们需要在MDIForm1中建立一个查找程序段。该程序段可以从当前编辑窗口的插入点位置开始向下搜索,搜索的内容是编辑窗口的FindStr属性指定的字符串。在RTF控件中本身提供了一个Find方法。该方法的语法以及解释如下:
    语法:object.Find(string,start,end,options)参数
    参数 描述
    string 必需的 要在控件中查找的字符串。
    start可选的 决定从哪儿开始搜索的整数字符索引。控件中的每一个字符都有一个可唯一标识的整数索引。控件中文本的第一个字符的索引是0。
    end 可选的 决定在哪儿结束搜索的整数字符索引。
    options       可选的 用来指定一个或多个可选功能常数的和。所指定的功能如"设置值"中所述。
    对options的设置值包括:
    常数                 值           描述
    rtfWholeWord         2          确定匹配是基于整个单词还是单词的片段。
    rtfMatchCase         4          确定匹配是否基于指定字符串与字符串文本的大小写字体一致。
    rtfNoHighlight       8         确定匹配是否在 RichTextBox 控件中突出显示。
    通过把它们的值或常数相加、或者用 Or 运算符使这些值相结合的形式,可使用多个选项。如果Find查找到了字符串,返回该字符串第一个字符的位置。否则返回-1。
    查找函数的具体实现如下:首先点击菜单的“Project|Add Module”项,在AddModule对话框中点击点击“打开”按钮添加一个Module到工程中,现在工程列表中的项目如图2所示。
     打开Module1,添加如下代码:
    Public Declare Function SendMessageByRef Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long,ByVal wMsg As Long,wParam As Long,lParam As Long) As Long
    Public Const EM_GETSEL=&HB0
    下面添加查找函数到MDIForm1。打开MDIForm1的代码窗口,在“通用”区域添加如下代码:
    Sub FindStrRTF(RTF As RichTextBox)
    Dim L1,L2 As Long
    If Me.ActiveForm.FindStr<>"" Then        利用API获得当前插入点位置
    SendMessageByRef RTF.hwnd,EM_GETSEL,L1,L2   要查找的字符串保存在FindStr属性中
    If RTF.Find(Me.ActiveForm.FindStr,L2)=-1 Then
     L2=0
    If RTF.Find(Me.ActiveForm.FindStr,L2)=-1 Then
    MsgBox Me.ActiveForm.FindStr+"没有找到",vbOKOnly,""
    End If
    End If
    End If
    End Sub
    在上面的程序段中我们第一次使用到Windows API(Application Programing Interface)调用,关于这方面的详细内容我们将在后面的章节中详细的讲,在这里你可以将SendMessageByRef函数看成一个VB中的函数。这个函数的作用是向窗口发送消息,在上面的程序中,我们使用 SendMessageByRef RTF.hwnd, EM_GETSEL, L1, L2 语句获取RTF控件的插入点的位置,保存在L2中。其中hwnd属性在以后利用API调用时会是很重要的。
    每一个Windows窗口(这里指的窗口是广义的。包括窗体、按钮、文本框等等)在建立时都会被赋予唯一的值用来标示窗口,这个值称为窗口句柄。而hwnd属性就是返回窗口的句柄。
    当获得了插入点位置后,接下来调用Find方法从该位置开始查找下一个符合条件的字符串,如果返回-1,说明已经查找完毕,这时将L2设置为0再执行Find方法,也就是从头查找。如果还是返回-1,说明文档中没有符合条件的字符串,这时使用MsgBox函数弹出对话框告知用户。
    打开MDIForm1,在菜单项mEditFind的Click事件中添加如下代码:
    With Me.ActiveForm
    If .RichTextBox1.SelText<>"" Then
    frmFind.txtFind.Text=.RichTextBox1.SelText
    ElseIf .FindStr<>"" Then
    frmFind.txtFind.Text=.FindStr
    End If
    frmFind.Show 0
    frmFind.txtFind.SetFocus
    frmFind.txtFind.SelStart=0
    frmFind.txtFind.SelLength=Len(frmFind.txtFind.Text)
    End With
    上面的程序只是实现了当用户点击查找菜单时弹出frmFind窗口,但是为了增加查找操作的方便性,增加了一些语句,这些语句的作用大家可以自己分析一下。接着就是编写查找窗口frmFind中的代码了,打开frmFind的代码窗口,在“通用”区域添加如下代码:
    Private Sub cmdCancel_Click()
    Me.Hide
    End Sub
    Private Sub cmdFind_Click()
    If txtFind.Text<>"" Then
    MDIForm1.ActiveForm.FindStr = txtFind.Text
    MDIForm1.FindStrRTF MDIForm1.ActiveForm.RichTextBox1
    Me.Hide
    Else    用户没有在文本框中输入任何文字
    Beep
    txtFind.SetFocus
    End If
    End Sub
    查找功能就完成了。现在来看一下效果,运行程序,打开一个文档,然后点击菜单的“编辑|查找”项,在查找窗口内输入查找文本,然后点击确定键,看看要查找的文本是否已经被高亮显示了呢?
    至于查找下一个功能就简单了,在MDIForm1的菜单项mEditFindNext的Click事件中
    加入下面一句就可以了:FindStrRTF Me.ActiveForm.RichTextBox1
    技巧与提示:焦点
    焦点就是在任何时间接收鼠标单击或键盘输入的能力。在Windows环境中,在同一时间只有一个窗口、窗体或控件具有这种能力。"具有焦点"的对象通常会以突出显示标题或标题栏来表示。用户或应用程序可设置焦点。在外观上,具有焦点的窗体的标题栏颜色为亮蓝,而没有焦点的窗体标题栏是灰色的。而一个窗体中只能有一个对象(按钮、文本框、列表框等)具有焦点,可以通过Tab键切换焦点,当然单击某个对象也可以使其获得焦点。但并不是所有对象都可以具有焦点,例如Label控件、Image控件就不具备接收焦点的能力。
    下面是关于控件焦点的几个问题:
    1.我如何得知控件获取或者失去焦点?
    控件有两个事件 GetFocus和LostFocus。当对象获得焦点时会引发GetFocus事件,而失去焦点时会引发LostFocus事件,例如下面的代码:
    Private Sub Text1_LostFocus()
    If Text1.Text="" Then
    MsgBox "你必须输入你的姓名"
    Text1.SetFocus
    End If
    End Sub
    当Text1失去焦点时,检查Text1中的文本是否为空,如果是,显示消息框提示输入姓名并将焦点转移到Text1上
    2.如何强制使控件获得焦点?
    可以利用SetFocus方法,上面的范例就是使用该方法使Text1获得焦点。
    3.如何得知窗体中那个控件具有焦点?
    可以通过访问窗体的ActiveControl属性获知。
    4.我在窗体中添加了若干TextBox控件用于输入用户信息,但是按tab键,焦点转移顺序并不是按我需要的方式,怎么办?
    能够接收焦点的控件有一个TabIndex属性,通过设置该属性可以控制tab键的焦点转移顺序。另外你可以通过TabStop属性来选择是否能够使用TAB键来将焦点从一个对象移动到另一个对象。
    本章功课:了解一下关于Windows API的基本知识,另外本章讲了关于焦点的问题,通过编写一些小程序来加深一下了解。
    (未完待续)(长沙 陈锐)  



----
我能翻译善写作熟电脑会说话可是为什么没工作?

[关闭][返回]