WIN32汇编语言教程:第09章 通用控件 · 9.4 使用Richedit控件(9)

5. 查找和替换

在Richedit控件中可以通过发送EM_FINDTEXT或者EM_FINDTEXTEX消息来完成查找字符串的功能,EM_FINDTEXTEX消息是EM_FINDTEXT消息的扩展,它们的用法是:

invoke SendMessage,hWinEdit,EM_FINDTEXT,uFlags,lpFindText
invoke SendMessage,hWinEdit,EM_FINDTEXTEX,uFlags,lpFindTextEx

消息的wParam参数中的uFlags指定查找的选项,它可以是以下取值的组合:

● FR_DOWN(2.0版本及以上使用)——向后查找,不设置的话表示向前查找。

● FR_MATCHCASE——查找字符串区分大小写。

● FR_WHOLEWORD——匹配整个单词。

EM_FINDTEXT的lParam参数指向一个FINDTEXT结构,而EM_FINDTEXTEX消息的lParam参数指向一个FINDTEXTEX结构,这两个结构的定义如下:

FINDTEXT STRUCT
 chrg            CHARRANGE <> ;查找区域
 lpstrText      DWORD     ?  ;查找字符串地址
FINDTEXT ENDS
FINDTEXTEX STRUCT
 chrg            CHARRANGE <> ;查找区域
 lpstrText      DWORD     ?  ;查找字符串地址
 chrgText       CHARRANGE <> ;如果找到则在这里返回找到文字的起始/结束位置
FINDTEXTEX ENDS

可以看出,EM_FINDTEXTEX消息的扩展之处在于直接在chrgText字段中返回找到文字的区域,程序可以马上使用这个区域数据进行其他操作,而EM_FINDTEXT消息必须根据找到的位置和查找字符串的长度自己计算这个区域。

两个消息的返回值是一样的,如果没有找到指定文字则返回−1,否则返回找到文字的起始位置。例子程序在_FindText子程序中完成查找功能,这个子程序分别在“查找下一个”、“查找上一个”和“查找文字”通用对话框的自定义消息中被调用,子程序中通过下面的代码来设置查找区域:

   invoke SendMessage,hWinEdit,EM_EXGETSEL,0,addr @stFindText.chrg
   .if    stFind.Flags & FR_DOWN
          push      @stFindText.chrg.cpMax
          pop    @stFindText.chrg.cpMin
   .endif
   mov    @stFindText.chrg.cpMax,-1

当找到一个匹配字符串后,字符串被设置为选择区域,如果向下继续查找下一个的话,必须将这个选择区域的结束位置用做下一次查找的起始点,所以程序发送EM_EXGETSEL消息获取选择区域并将cpMax字段放到cpMin字段中,并将cpMax字段设置为-1,表示一直查找到全部文本的最后。

在第08章中已经有所介绍:“查找文字”通用对话框使用FINDREPLACE结构,不知道是巧合还是Microsoft的故意安排,FINDREPLACE结构中的Flags字段和EM_FINDTEXTEX消息中的wParam参数的标志定义是一样的,所以程序直接取出Flags字段,然后屏蔽掉FR_MATCHCASE,FR_DOWN和FR_WHOLEWORD等不需要使用的标志以后,就可以直接在消息的wParam参数中使用了:

   mov    ecx,stFind.Flags
   and    ecx,FR_MATCHCASE or FR_DOWN or FR_WHOLEWORD
   invoke SendMessage,hWinEdit,EM_FINDTEXTEX,ecx,addr @stFindText

找到字符串以后,进行替换操作就不是一件复杂的事情了,因为FINDTEXTEX结构的chrgText字段中已经返回了找到文本的起始和结束位置,将它设置为选择区域以后就可以通过发送EM_REPLACESEL消息进行替换操作了。

9.4.3  Richedit控件的通知消息

Richedit控件也可以向父窗口发送多种通知消息,使用“可以”一词的意思是,控件在默认状态下并不发送通知消息,如果需要控件发送某个消息,必须首先对控件进行设置。通过向Richedit控件发送EM_SETEVENTMASK消息可以激活需要的通知消息:

   invoke SendMessage,hWinEdit,EM_SETEVENTMASK,0,dwMask

dwMask是事件掩码,可以是下面标志的组合,分别代表激活不同的通知消息:

● ENM_CHANGE——允许EN_CHANGE通知码,本消息在用户的操作可能改变控件中的文本的时候发送。

● ENM_CORRECTTEXT——允许EN_CORRECTTEXT通知码。

● ENM_DRAGDROPDONE——允许EN_DRAGDROPDONE通知码,本消息在用户完成了一个拖放操作后发送。

● ENM_DROPFILES——允许EN_DROPFILES通知码,本消息在用户将一个文件拖放进控件后发送。

● ENM_KEYEVENTS——允许为键盘消息发送EN_MSGFILTER通知码。

● ENM_MOUSEEVENTS——允许为鼠标消息发送EN_MSGFILTER通知码。

● ENM_PROTECTED——允许发送EN_PROTECTED通知码。

● ENM_SCROLL——允许发送EN_HSCROLL和EN_VSCROLL通知码。

● ENM_SCROLLEVENTS——允许为鼠标滑轮发送EN_MSGFILTER通知码。

● ENM_SELCHANGE——允许发送EN_SELCHANGE通知码,本消息在选择区域改变以后发送(包括光标位置改变)。

● ENM_UPDATE——允许发送EN_UPDATE通知码,本消息在控件将要显示被改变的文本之前发送。

当这些通知消息被激活的时候,父窗口就可以收到包含相应通知码的WM_NOTIFY消息。一般来说,将控件设置为仅发送程序感兴趣的通知消息,如当在Richedit控件中按下右键需要弹出一个菜单的时候,需要检测鼠标消息,那么就需要指定ENM_MOUSEEVENTS标志;另外,如果需要随时检测选择区域的状态,以便随时设置工具栏中“拷贝”与“剪切”等按钮的状态,那么就要使用ENM_SELCHANGE标志,这样光标一移动或者选择区域一改变,父窗口就可以收到EN_SELCHANGE通知码,于是程序就可以在WM_NOTIFY消息中随时改变工具栏上各按钮的状态。

由于Richedit.asm例子中没有使用工具栏,所以没有对通知消息进行示例,有兴趣的读者可以查看所附光盘的Chapter09\Wordpad目录中的例子文件,这个例子中使用工具栏和状态栏等控件,需要随时显示光标位置等信息,程序中就包含了处理通知消息的代码。

上页:第09章 通用控件 · 9.4 使用Richedit控件(8) 下页:第09章 通用控件 · 9.5 窗口的子类化(1)

第09章 通用控件

版权所有 © 中山市飞娥软件工作室 证书:粤ICP备09170368号