windows环境下32位汇编语言程序设计-第58部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
■ CFE_BOLD,CFE_ITALIC,CFE_STRIKEOUT和CFE_UNDERLINE——粗体字符、斜体字符、带删除线和带下划线。
■ CFE_PROTECTED——字符是受保护的,企图改变字符的话控件会向父窗口发送一个EN_PROTECTED通知消息。
● yHeight——字符高度,单位是1/1 440 英寸(或1/20磅),如果这里是180,换算到“字体选择”通用对话框中的尺寸就是9磅(180×1/20=9)。
● yOffset——从基线算起的字符偏移,单位同上,如果该成员是正值,字符显示为上标;如果是负值,字符显示为下标。
● crTextColor——正文颜色,如果在dwEffects字段中指定了CFE_AUTOCOLOR标志,那么这个值会被忽略。
● bCharSet和bPitchAndFamily——字符集。
● szFaceName——用字符串表示的字体名字。
通过填充这个结构并将它通过EM_SETCHARFORMAT消息传送给控件,可以改变文字的效果(粗体、斜体、带删除线、带下划线等),正文颜色(crTextColor),字体外观(szFaceName)和字体大小(yHeight),以及使用的字符集等。使用CHARFORMAT2结构可以设置更多的文本风格,如字间距与正文背景色等。如果不需要这些额外的功能,那么只要使用CHARFORMAT结构就可以了。
例子程序Richedit。asm中只演示了使用Plain Text模式为所有文本设置字体的方法:
nst
szFont db '宋体';0
de
invoke SendMessage;hWinEdit;EM_SETTEXTMODE;TM_PLAINTEXT;0
invoke RtlZeroMemory;addr @stCf;sizeof @stCf
mov @stCf。cbSize;sizeof @stCf
mov @stCf。yHeight;9 * 20
mov @stCf。dwMask;CFM_FACE or CFM_SIZE or CFM_BOLD
invoke lstrcpy;addr @stCf。szFaceName;addr szFont
invoke SendMessage;hWinEdit;EM_SETCHARFORMAT;0;addr @stCf
程序首先将控件的模式设置为Plain Text模式,然后定义了一个名为@stCf的CHARFORMAT结构,将结构长度设置为CHARFORMAT结构的长度,然后在dwMask 字段中使用CFM_FACE, CFM_SIZE和CFM_BOLD标志,表示只使用字体、字体大小和字体粗细参数,最后发送EM_SETCHARFORMAT消息将控件中的全部文字设置为大小为9磅(小五号)的“宋体”。
4。 装入和保存文本
显然,使用GetWindowText和SetWindowText函数来保存和装入文本是可行的,但是RichEdit控件支持很大的文件,当文件足够大的时候,使用这种方法就很麻烦,因为必须首先要分配一块足够大的内存用做缓冲区,为了解决这个问题,Richedit控件提供了一种新方法,那就是文本流(Text Streaming)。
考虑这样一种情况:为了装入文本,可以申请一块大小合适的缓冲区(当然不会大到能容纳全部文本),每次从文件中读入缓冲区大小的文本并添加到控件中,如此循环直到读入全部文本;保存文本的时候,同样可以每次从控件中取出缓冲区大小的文本,然后写入文件,如此循环直到处理完控件中的全部文本。
文本流的操作方法与此类似,只不过缓冲区和循环都封装在控件的内部,而我们通过提供回调函数的办法提供读写文件的功能模块,Richedit控件循环调用这个模块直到处理完全部的内容。每次调用的时候,控件通过参数告诉回调函数要读写的字节数和缓冲区的地址。文本的流入和流出使用EM_STREAMIN和EM_STREAMOUT消息,这两个消息的使用格式是一样的:
invoke SendMessage;hWinEdit;EM_STREAMIN;uFormat;lpStream
invoke SendMessage;hWinEdit;EM_STREAMOUT;uFormat;lpStream
wParam参数中的uFormat指定需要流入/流出的内容,它可以是以下的取值:
● SF_RTF——文本格式是RTF格式。
● SF_TEXT——文本是Plain Text格式,也就是简单的文本格式。
● SFF_SELECTION——流操作的范围是当前选择区域。如果将文本流入,当前选择区域就会被替换;如果是流出,则只有那些当前选定的文本才流出。如果没有指定这个标志,操作范围是控件中的所有文本。
● SF_UNICODE——指定的是 Unicode 文本(2。0及以上版本提供)。
lParam参数中的lpStream指向一个EDITSTREAM 结构,该结构定义如下:
EDITSTREAM STRUCT
dwCookie DWORD ? ;用户自定义值
dwError DWORD ? ;用来返回流操作过程中的错误信息
pfnCallback DWORD ? ;回调函数地址
EDITSTREAM ENDS
结构中各字段的说明如下:
● dwCookie——应用程序自定义的数值,这个数值将会传递给回调函数。
● dwError——指示流操作的结果,0说明没有错误。
● pfnCallback——指向回调函数,该函数由用户定义,并由RichEdit控件调用来传输文本。RichEdit控件将文本分成多个部分,每次调用该函数处理一个部分,直到全部文本被处理为止。
回调函数的定义如下:
EditStreamCallback proc dwCookie;lpBuffer;NumBytes; pBytesTransferred
控件传递给回调函数的参数说明如下:
● dwCookie——就是消息中指定的EDITSTREAM结构中定义的dwCookie值。
● lpBuffer——指向Richedit控件提供的缓冲区。对于流入操作,这里用来接收流入的文本;对于流出操作,这里存放要流出的文本。
● NumBytes——本次调用中可以操作的字节数。对于流入操作,表示可以写入缓冲区的最大字节数;对于流出操作,表示需要流出的文本的长度。
● pBytesTransferred——指向一个双字,由于实际操作的字节数不一定等于NumBytes参数指定的数值(比如流入时读到了文件尾部),操作后必须在这里返回实际操作的字节数。
回调函数返回0说明操作成功,这样如果还有数据需要读写,RichEdit控件就会继续调用它。如果操作中发生了错误,而且程序需要停止操作的话,可以返回一个非0值,这时Richedit控件就会丢弃lpBuffer指向的数据并停止对回调函数的继续调用。当消息返回的时候,由回调函数返回的错误/成功值会在EDITSTREAM结构的dwError字段中返回,所以可以在SendMessage返回后以此检查流操作是否成功。
在例子文件中,进行流操作如下:
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 回调函数
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
_ProcStream proc uses ebx edi esi _dwCookie;_lpBuffer;_dwBytes;_lpBytes
。if _dwCookie
invoke ReadFile;hFile;_lpBuffer;_dwBytes;_lpBytes;0
。else
invoke WriteFile;hFile;_lpBuffer;_dwBytes;_lpBytes;0
。endif
xor eax;eax
ret
_ProcStream endp
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 流出操作
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
mov @stES。dwCookie;FALSE ; @stES是一个EDITSTREAM结构
mov @stES。pfnCallback;offset _ProcStream
invoke SendMessage;hWinEdit;EM_STREAMOUT;SF_TEXT;addr @stES
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 流入操作
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
mov @stES。dwCookie;TRUE
mov @stES。pfnCallback;offset _ProcStream
invoke SendMessage;hWinEdit;EM_STREAMIN;SF_TEXT;addr @stES
程序中流入和流出操作的回调函数使用同一个子程序,通过设置EDITSTREAM结构的自定义值dwCookie字段来表示进行的是流入还是流出的操作,子程序中通过判断dwCookie参数是TRUE还是FALSE来决定进行读文件还是写文件的操作(读写文件的函数ReadFile和WriteFile的用法请参考第10章)。
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第9章 通用控件
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,表示一直查找到全部文本的最后。
在第8章中已经有所介绍:“查找文字”通用对话框使用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通知�