?? lion-tut-c34.htm
字號:
<HTML>
<head>
<link rel="stylesheet" href="../../asm.css">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>
<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<H1 align=center><FONT color=#0000ff face=Tahoma>教程 34: RichEdit 控件:更多的正文操作</FONT></H1>
<P align=left><FONT face=Tahoma size=-1>你將會了解到關于的RichEdit更多的正文操作。特別是你將會學習到如何搜索/替換正文,定位到某一指定的行號。</FONT></P>
<P align=left><FONT face=Tahoma size=-1>下載 <A
href="files/tut34.zip">例子程序</A>.</FONT></P>
<H3 align=left><FONT color=#0000ff
face="Times New Roman, Times, serif">Theory</FONT></H3>
<H3 align=left><FONT color=#990099 face="Arial, Helvetica, sans-serif">Searching
for Text</FONT></H3>
<P align=left><FONT face=Tahoma size=-1>RichEdit 控件具有幾種正文操作,搜索指定正文就是其中的一種。搜索正文是通過發送 <FONT color=#006666><B>EM_FINDTEXT</B></FONT> 或者 <FONT
color=#006666><B>EM_FINDTEXTEX</B></FONT> 消息來完成的。這兩個消息有一點很小的不同點。</FONT></P>
<BLOCKQUOTE><PRE align="left"><FONT face=Tahoma><B><FONT color=#006666>EM_FINDTEXT</FONT></B>
<FONT color=#000099><B>wParam</B></FONT> == 搜索選項。 可以是下表中的任意組合值。這些選項對 <FONT color=#006666><B>EM_FINDTEXT</B></FONT> 和 <FONT color=#006666><B>EM_FINDTEXTEX</B></FONT> 都是一樣的。</FONT></PRE>
<TABLE align=center border=1 cellPadding=3>
<TBODY>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>FR_DOWN</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>如果指定了這個標志值,搜索操作從當前選定的 <FONT color=#0000cc><B>end</B></FONT> 位置開始,直到控件中正文的 <FONT color=#0000cc><B>end</B></FONT> 位置結束(<FONT color=#0000ff><B>向下搜索</B></FONT>)。這個標志僅影響 RichEdit 2.0 和以后版本: <FONT
color=#cc00cc><B>這個是 RichEdit 1.0 的缺省行為</B></FONT>。RichEdit 2.0 或以后版本的缺省行為是在當前選定正文內的從結尾搜索到開始位置(<FONT color=#0000ff><B>向前搜索</B></FONT>)。<BR>概括來說就是,如果你使用 RichEdit 1.0, 無論你做什么都沒法影響搜索的方向:它總使用向后搜索。但是如果你使用 RichEdit 2.0 而且你想使用向后搜索的話,你<FONT color=#cc00cc><B>必須</B></FONT>指定這個標志值,否則使用的是向前搜索了。</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>FR_MATCHCASE</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>如果指定了這個標志值,搜索操作是大小寫敏感的,即區分大小寫。</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>FR_WHOLEWORD</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>如果設置了這個標志值,搜索操作就搜尋匹配指定搜索串的整個詞。</FONT></TD></TR></TBODY></TABLE><PRE><FONT face=Tahoma>實際上,還有更多的標志值,但是它們都是跟非英語系正文操作相關的。
lParam == <FONT color=#006666><B>FINDTEXT</B></FONT> 結構的指針。
<FONT color=#990099><B> FINDTEXT <FONT color=#0000cc>STRUCT</FONT>
chrg <FONT color=#0000cc>CHARRANGE</FONT> <>
lpstrText <FONT color=#0000cc>DWORD</FONT> ?
FINDTEXT <FONT color=#0000cc>ENDS</FONT></B></FONT>
<FONT color=#990099><B>chrg</B></FONT> 是一個 <FONT color=#006666><B>CHARRANGE</B></FONT> 結構,其定義如下:
<FONT color=#cc00cc><B> CHARRANGE <FONT color=#0000cc>STRUCT</FONT>
cpMin <FONT color=#0000cc>DWORD</FONT> ?
cpMax <FONT color=#0000cc>DWORD</FONT> ?
CHARRANGE <FONT color=#0000cc>ENDS</FONT></B></FONT>
<FONT color=#0000cc><B>cpMin</B></FONT> 包含字符數組中第一個字符的字符索引。
<FONT color=#0000cc><B>cpMax</B></FONT> 包含緊跟在字符數組中最后一個字符的字符的字符索引。
基本上,要搜索一個正文串,你必須指定要搜索的字符范圍。
<FONT color=#cc0033><B><FONT color=#0000cc>cpMin</FONT> 和 <FONT color=#0000cc>cpMax</FONT> 的具體意義根據搜索是向后還是向前是不同的</B></FONT>。
如果是向后搜索,<FONT color=#0033cc><B>cpMin</B></FONT> 指定搜索的開始字符索引,而 <FONT color=#0000cc><B>cpMax</B></FONT> 則是結束字符索引。
如果是向前搜索,則反過來才對,也就是說 <FONT color=#0000cc><B>cpMin</B></FONT> 包含結束字符索引而<FONT color=#0000cc><B>cpMax</B></FONT> 包含開始字符索引。
<FONT color=#cc00cc><B>lpstrText</B></FONT> 是要搜索的正文串的指針。
<FONT color=#0000cc><B>EM_FINDTEXT</B></FONT> 返回控件中跟搜索串匹配的的正文串的一個字符的索引。如果沒找到匹配的則返回 -1。
<FONT color=#006666><B>EM_FINDTEXTEX</B></FONT>
<FONT color=#0000cc><B>wParam</B></FONT> == 搜索選項,跟 <FONT color=#006666><B>EM_FINDTEXT</B></FONT> 的一樣。
<FONT color=#000099><B>lParam</B></FONT> == <FONT color=#006666><B>FINDTEXTEX</B></FONT> 結構的指針。
<FONT color=#990099><B> FINDTEXTEX <FONT color=#0000cc>STRUCT</FONT>
chrg <FONT color=#0000cc>CHARRANGE</FONT> <>
lpstrText <FONT color=#0000cc>DWORD</FONT> ?
chrgText <FONT color=#0000cc>CHARRANGE</FONT> <>
FINDTEXTEX <FONT color=#0000cc>ENDS
</FONT></B></FONT><FONT color=#006666><B>FINDTEXTEX</B></FONT> 中開始的兩個成員是跟 <FONT color=#006666><B>FINDTEXT</B></FONT> 結構中的一樣的。
chrgText 是一個 <FONT color=#006666><B>CHARRANGE</B></FONT> 結構,如果搜索到匹配串的話,其開始/結束字符索引會被填入這個結構中。
<FONT color=#006666><B>EM_FINDTEXTEX</B></FONT> 的返回值跟 <FONT color=#006666><B>EM_FINDTEXT</B></FONT>的是一樣的。
<FONT color=#006666><B>EM_FINDTEXT </B></FONT> 跟 <FONT color=#006666><B> EM_FINDTEXTEX</B></FONT> 的不同處是 <FONT color=#006666><B>FINDTEXTEX</B></FONT> 結構有一個另外的<FONT color=#006666><B>chrgText</B></FONT>成員, 如果搜索到匹配串的話,
其開始/結束字符索引會被填入這個成員中。如果我們想對這個正文串進行更多的正文操作的話,有這個就方便多了。</FONT></PRE></BLOCKQUOTE>
<H3><FONT color=#990099 face="Arial, Helvetica, sans-serif">替換/插入正文</FONT><FONT face=Tahoma> </FONT></H3>
<P><FONT face=Tahoma size=-1>RichEdit 控件提供了 <FONT
color=#006666><B>EM_SETTEXTEX</B></FONT> 來進行正文替換/插入操作。這個消息混合了 <FONT
color=#006666><B>WM_SETTEXT</B></FONT> 和 <FONT
color=#006666><B>EM_REPLACESEL</B></FONT> 的功能. 它具有以下語法:</FONT></P><PRE><FONT face=Tahoma> <FONT color=#006666><B>EM_SETTEXTEX</B></FONT>
<FONT color=#0000cc><B>wParam</B></FONT> == <FONT color=#006666><B>SETTEXTEX</B></FONT> 結構的指針。
<FONT color=#990099><B> SETTEXTEX <FONT color=#0000cc>STRUCT</FONT>
flags <FONT color=#0000cc>DWORD</FONT> ?
codepage <FONT color=#0000cc>DWORD</FONT> ?
SETTEXTEX <FONT color=#0000cc>ENDS</FONT></B></FONT>
<FONT color=#990099><B>flags</B></FONT> 可以是以下值的組合:</FONT></PRE>
<TABLE align=center border=1 cellPadding=3>
<TBODY>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ST_DEFAULT</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>刪除Undo堆棧,丟棄RTF格式,替換所有的正文。</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ST_KEEPUNDO</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>保留Undo堆棧。</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ST_SELECTION</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>替換選定正文并且保留RTF格式</FONT></TD></TR></TBODY></TABLE><PRE><FONT face=Tahoma> <FONT color=#990099><B>codepage</B></FONT> 是一個常量,指定你的正文想要的代碼頁。我們通常簡單的使用 <FONT color=#006666><B>CP_ACP</B></FONT>。</FONT></PRE>
<H3><FONT color=#990099 face=Tahoma>正文選擇</FONT></H3>
<P><FONT face=Tahoma size=-1>我們可以使用消息 <FONT
color=#000099><B><FONT color=#006666>EM_SETSEL</FONT></B></FONT> 或者 <FONT
color=#006666><B>EM_EXSETSEL</B></FONT> 來編程選擇正文.其中任意的一個都可以工作的很好。要使用哪一個消息要根據可用的字符索引格式來選擇。如果它們保存在一個 <FONT color=#006666><B>CHARRANGE</B></FONT> 結構中,則使用 <FONT color=#006666><B>EM_EXSETSEL</B></FONT>更容易實現。</FONT><FONT
face=Tahoma><BR></FONT></P><PRE><FONT face=Tahoma> <FONT color=#006666><B>EM_EXSETSEL</B></FONT>
<FONT color=#0000cc><B>wParam</B></FONT> == 沒有使用,必須為 0 。
<FONT color=#0000cc><B>lParam</B></FONT> == <FONT color=#006666><B>CHARRANGE</B></FONT> 結構的指針,包含想要選定的正文字符范圍。</FONT></PRE>
<H3><FONT color=#990099 face=Tahoma>事件通知</FONT></H3>
<P><FONT face=Tahoma size=-1>在使用多行Edit控件時,你必須子類化它以便得到輸入信息象鼠標/鍵盤事件等。RichEdit 控件提供了一個更好的方案,它可以把這些消息通知父窗口。為了注冊得到通知消息,父窗口發送 <FONT color=#006666><B>EM_SETEVENTMASK</B></FONT> 消息給 RichEdit 控件,指定它對哪些消息感興趣。 <FONT
color=#006666><B>EM_SETEVENTMASK </B></FONT>具有以下的語法:</FONT></P><PRE><FONT face=Tahoma> <B><FONT color=#006666>EM_SETEVENTMASK</FONT></B>
<FONT color=#000099><B>wParam</B></FONT> == 沒有使用,必須為 0 。
<FONT color=#0000cc><B>lParam</B></FONT> == 事件掩碼值。他可以是以下表格里標志值的任意組合。</FONT></PRE>
<TABLE align=center border=1 cellPadding=3>
<TBODY>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_CHANGE</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>發送 <FONT
color=#000099><B>EN_CHANGE</B></FONT> 通知</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_CORRECTTEXT</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>發送 <FONT
color=#000099><B>EN_CORRECTTEXT</B></FONT> 通知</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_DRAGDROPDONE</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>發送 <FONT
color=#0000cc><B>EN_DRAGDROPDONE</B></FONT> 通知</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_DROPFILES</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>發送 <FONT
color=#0000cc><B>EN_DROPFILES</B></FONT> 通知</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_KEYEVENTS</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>為鍵盤消息發送 <FONT
color=#0000cc><B>EN_MSGFILTER </B></FONT>通知</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_LINK</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1><B>Rich Edit 2.0 或以后版本:</B>
當鼠標在具有 <FONT color=#990099><B>CFE_LINK</B></FONT> 風格的正文上面移過,而且執行了一個或幾個鼠標動作時,就發送 <FONT color=#0000cc><B>EN_LINK</B></FONT> 通知。</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_MOUSEEVENTS</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>為鼠標消息發送 <FONT
color=#0000cc><B>EN_MSGFILTER</B></FONT> 通知。</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif"
size=-1>ENM_OBJECTPOSITIONS</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>發送 <FONT
color=#0000cc><B>EN_OBJECTPOSITIONS</B></FONT> 通知</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_PROTECTED</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>發送 <FONT color=#0000cc><B>
EN_PROTECTED</B></FONT> 通知</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_REQUESTRESIZE</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>發送 <FONT color=#0000cc><B>
EN_REQUESTRESIZE</B></FONT> 通知</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_SCROLL</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>發送 <FONT
color=#0000cc><B>EN_HSCROLL</B></FONT> 和 <FONT
color=#000099><B>EN_VSCROLL</B></FONT> 通知</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_SCROLLEVENTS</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>為鼠標滑輪發送 <FONT
color=#0000cc><B>EN_MSGFILTER</B></FONT> 通知。</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><B><FONT face="MS Sans Serif" size=-1>ENM_SELCHANGE</FONT></B></TD>
<TD><FONT face="MS Sans Serif" size=-1>發送 <FONT
color=#000099><B>EN_SELCHANGE</B></FONT> 通知</FONT></TD></TR>
<TR bgColor=#ffffcc>
<TD><FONT face="MS Sans Serif" size=-1><B>ENM_UPDATE</B></FONT></TD>
<TD>
<P><FONT face="MS Sans Serif" size=-1>發送 <FONT
color=#0000cc><B>EN_UPDATE </B></FONT>通知<BR><B>Rich Edit 2.0
和以后版本: </B>這個標志值會被忽略,而經常發送 <FONT
color=#0000cc><B>EN_UPDATE</B></FONT> 通知。然而如果 RichEdit 3.0 模擬 RichEdit 1.0的話,你必須使用這個標志值來發送 <FONT color=#000099><B>EN_UPDATE</B></FONT> 通知
</FONT></P></TD></TR></TBODY></TABLE>
<P><FONT face=Tahoma size=-1>上面的所有通知都被做為 <FONT
color=#006666><B>WM_NOTIFY </B></FONT> 消息來發送:你必須檢查 <FONT color=#006666><B>NMHDR</B></FONT> 結構的 code 成員來得到通知消息。譬如,如果你想注冊得到鼠標消息(也就是說,你想提供一給上下文相關的彈出菜單), 你需要象下面這樣做:</FONT></P><PRE><FONT face=Tahoma><B> invoke SendMessage,hwndRichEdit,<FONT color=#006666>EM_SETEVENTMASK</FONT>,0,<FONT color=#0000ff>ENM_MOUSEEVENTS</FONT>
.....
.....
WndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
.....
....
.elseif uMsg==WM_NOTIFY
push esi
mov esi,lParam
assume esi:ptr NMHDR
<FONT color=#ff0033>.if [esi].code==EN_MSGFILTER</FONT>
....
[ do something here]
....
.endif
pop esi</B></FONT></PRE>
<H3><FONT face="Times New Roman, Times, serif">例子:</FONT></H3>
<P><FONT face=Tahoma size=-1>下面的例子是第33篇指南里的 IczEdit 的改進版。它為程序增加了搜索/替換功能和加速鍵。同時它處理鼠標消息,點右鍵時會出現一個彈出菜單。</FONT></P><PRE><FONT face=Tahoma><B>.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\gdi32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
.const
IDR_MAINMENU equ 101
IDM_OPEN equ 40001
IDM_SAVE equ 40002
IDM_CLOSE equ 40003
IDM_SAVEAS equ 40004
IDM_EXIT equ 40005
IDM_COPY equ 40006
IDM_CUT equ 40007
IDM_PASTE equ 40008
IDM_DELETE equ 40009
IDM_SELECTALL equ 40010
IDM_OPTION equ 40011
IDM_UNDO equ 40012
IDM_REDO equ 40013
IDD_OPTIONDLG equ 101
IDC_BACKCOLORBOX equ 1000
IDC_TEXTCOLORBOX equ 1001
IDR_MAINACCEL equ 105
IDD_FINDDLG equ 102
IDD_GOTODLG equ 103
IDD_REPLACEDLG equ 104
IDC_FINDEDIT equ 1000
IDC_MATCHCASE equ 1001
IDC_REPLACEEDIT equ 1001
IDC_WHOLEWORD equ 1002
IDC_DOWN equ 1003
IDC_UP equ 1004
IDC_LINENO equ 1005
IDM_FIND equ 40014
IDM_FINDNEXT equ 40015
IDM_REPLACE equ 40016
IDM_GOTOLINE equ 40017
IDM_FINDPREV equ 40018
RichEditID equ 300
.data
ClassName db "IczEditClass",0
AppName db "IczEdit version 2.0",0
RichEditDLL db "riched20.dll",0
RichEditClass db "RichEdit20A",0
NoRichEdit db "Cannot find riched20.dll",0
ASMFilterString db "ASM Source code (*.asm)",0,"*.asm",0
db "All Files (*.*)",0,"*.*",0,0
OpenFileFail db "Cannot open the file",0
WannaSave db "The data in the control is modified. Want to save it?",0
FileOpened dd FALSE
BackgroundColor dd 0FFFFFFh <FONT color=#009999>; default to white</FONT>
TextColor dd 0 <FONT color=#009999> ; default to black</FONT>
hSearch dd ? <FONT color=#006666> ; handle to the search/replace dialog box</FONT>
hAccel dd ?
.data?
hInstance dd ?
hRichEdit dd ?
hwndRichEdit dd ?
FileName db 256 dup(?)
AlternateFileName db 256 dup(?)
CustomColors dd 16 dup(?)
FindBuffer db 256 dup(?)
ReplaceBuffer db 256 dup(?)
uFlags dd ?
findtext FINDTEXTEX <>
.code
start:
mov byte ptr [FindBuffer],0
mov byte ptr [ReplaceBuffer],0
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke LoadLibrary,addr RichEditDLL
.if eax!=0
mov hRichEdit,eax
invoke WinMain, hInstance,0,0, SW_SHOWDEFAULT
invoke FreeLibrary,hRichEdit
.else
invoke MessageBox,0,addr NoRichEdit,addr AppName,MB_OK or MB_ICONERROR
.endif
invoke ExitProcess,eax
WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:DWORD
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,IDR_MAINMENU
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
invoke LoadAccelerators,hInstance,IDR_MAINACCEL
mov hAccel,eax
.while TRUE
invoke GetMessage, ADDR msg,0,0,0
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -