18第三十三课 RichEdit 控件基础知识_第1页
18第三十三课 RichEdit 控件基础知识_第2页
18第三十三课 RichEdit 控件基础知识_第3页
18第三十三课 RichEdit 控件基础知识_第4页
18第三十三课 RichEdit 控件基础知识_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

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

文档简介

第三十三课:RichEdit控件基础知识有很多人要求我提供关于RichEdit控件的指南,经过这方面的大量编程实践,我想我终于可以开写关于RichEdit控件的指南了。诺,这个就是第一篇RichEdit指南。本指南将会描述涉及到RichEdit的几乎所有方面,起码是我所知道的关于它的所有方面。因为指南的信息量相当相当的大,所以我将它分成了几个部分,本篇是第一部分。在这篇指南里,你将会了解到什么是RichEdit控件,怎样创建它,怎样往里面载入数据和保存里面的数据。例子理论Aricheditcontrolcanbethoughtofasasouped-upeditcontrol.它提供了普通简单Edit控件所缺少的很多令人合意的功能,譬如可以使用多种字体和字体大小,多级Undo/Redo,文本搜索,内嵌OLE对象,编辑的拖放支持等等。由于RichEdit控件有这么多功能,因此它独存于一个单独的DLL文件。这个意味着如果你要使用RichEdit控件,就不能象使用其他普通控件那样只调用InitCommonControls函数。你必须先使用LoadLibrary来载入RichEditDLL文件。这里有个问题,就是至今为止RichEdit控件共有3个版本,版本1,2和3。下面的表格显示了每个版本的相应的DLL文件名。DLLNameRichEditversionRicheditClassNameRiched32.dll1.0RICHEDITRichEd20.dll2.0RICHEDIT20ARichEd20.dll3.0RICHEDIT20A你会注意到版本2和3都使用了相同的DLL文件名,而且它们也使用了相同的类名!这样在你想要明确的使用RichEdit3.0的功能的时候就会产生问题.到目前为止,我还找到一个正式的方法来区分版本2.0和3.0.不过,有个解决方法工作良好,我会在后面演示给你看..dataRichEditDLLdb"RichEd20.dll",0 ......data? hRichEditDLLdd?.code invokeLoadLibrary,addrRichEditDLL movhRichEditDLL,eax ...... invokeFreeLibrary,hRichEditDLL当RicheditDLL文件被载入时,它会注册RichEdit窗口类,因此需要在你创建Richedit控件之前必须先要载入DLL.Richedit控件的类名是不同的。现在你可能会有一个问题要提:我怎么样才能够知道我要使用哪个版本的Richedit控件?如果你不需要使用那些特别的功能,使用最新的版本也不定是最适宜的.下面的表格列出了每个RichEdit版本提供的功能.功能版本1.0版本2.0版本3.0选择条xxxUnicode编辑

xx字符段落格式xxx文本搜索向前搜索向前/向后搜索向前/向后搜索内嵌OLExxx拖放编辑xxxUndo/Redo单级多级多级自动URL识别

xx加速键支持

xx非窗口操作

xx分行符CRLFCRCR(可以模拟1.0版本)Zoom

xParagraphnumbering

xsimpletable

xnormalandheadingstyles

xunderlinecoloring

xhiddentext

xfontbinding

x上面的表格不是全面的:我只是列出了那些重要的功能.创建RchEdit控件载入DLL文件后,你可以调用CreateWindowEx来创建RichEdit控件,创建控件时你可以使用Edit控件风格和普通窗口风格,但是ES_LOWERCASE,ES_UPPERCASE和ES_OEMCONVERT风格除外..const RichEditIDequ300.data RichEditDLLdb"RichEd20.dll",0 RichEditClassdb"RichEdit20A",0 ....data? hRichEditDLLdd? hwndRichEditdd?.code ..... invokeLoadLibrary,addrRichEditDLL movhRichEditDLL,eax invokeCreateWindowEx,0,addrRichEditClass,WS_VISIBLEorES_MULTILINEorWS_CHILDorWS_VSCROLLorWS_HSCROLL,\ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hWnd,RichEditID,hInstance,0 movhwndRichEdit,eax设置缺省的文本和背景颜色在使用Edit控件时设置文本和背景颜色可能有点问题,但是在RichEdit控件中已经修正了这个问题.要设置RichEdit的背景色,你要发送EM_SETBKGNDCOLOR消息给RichEdit控件.这个消息具有以下语法.wParam==颜色选项.如果是0说明Windows使用lParam中的颜色值作为背景色.如果该参数不为0,Windows使用系统背景色.因为我们要发送该消息来改变背景色,所以我们必须令wParam为0.

lParam==指定要设置的颜色的COLORREF结构,仅当wParam为0时才有效.譬如,如果我要设置背景为纯蓝色,我需要写入以下代码: invokeSendMessage,hwndRichEdit,EM_SETBKGNDCOLOR,0,0FF0000h要设置文本颜色,RichEdit控件提供了另外的新消息,EM_SETCHARFORMAT来做这个工作.这个消息控制控件中一段选定的文本或者全部正文的格式.这个消息的语法如下:wParam==格式选项:SCF_ALL本次操作影响控件中全部文本.SCF_SELECTION本次操作仅影响选定的文本SCF_WORDorSCF_SELECTION本次操作仅影响所选定的那个单词.如果选定是空的话,仅将插入点(光标)设置到指定字的位置.SCF_WORD标志必须跟SCF_SELECTION一起使用.lParam==CHARFORMAT或者CHARFORMAT2结构的指针,说明要使用的正文格式.CHARFORMAT2只在Richedit2.0和更高版本才提供.这个不是说在RichEdit2.0以后你一定要使用CHARFORMAT2.如果你不需要使用到CHARFORMAT2中新加的功能,你仍然可以使用CHARFORMAT.CHARFORMATASTRUCT cbSizeDWORD? dwMaskDWORD? dwEffectsDWORD? yHeightDWORD? yOffsetDWORD? crTextColorCOLORREF? bCharSetBYTE? bPitchAndFamilyBYTE? szFaceNameBYTELF_FACESIZEdup(?) _wPad2WORD?CHARFORMATAENDSFieldNameDescriptioncbSize该结构的大小.RichEdit控件使用该域来判断该结构的版本是CHARFORMAT还是CHARFORMAT2dwMask位标记,用来指定下面的那些成员是有效的.CFM_BOLDdwEffects成语中的CFE_BOLD值是有效的.CFM_CHARSETbCharSet成员是有效的。CFM_COLORcrTextColor成员跟dwEffects中的CFE_AUTOCOLOR值是有效的.CFM_FACEszFaceName成员是有效的.CFM_ITALICdwEffects成员中的CFE_ITALIC值是有效的.CFM_OFFSETyOffset成员是有效的.CFM_PROTECTEDdwEffects成员中的CFE_PROTECTED值是有效的.CFM_SIZEyHeight成员是有效的.CFM_STRIKEOUTdwEffects成员中的CFE_STRIKEOUT值是有效的.CFM_UNDERLINEdwEffects成员中的CFE_UNDERLINE值是有效的.dwEffects字符效果.可以是以下值的组合CFE_AUTOCOLOR使用系统正文颜色CFE_BOLD粗体字符CFE_ITALIC斜体字符CFE_STRIKEOUT字符带删除线CFE_UNDERLINE字符带下划线CFE_PROTECTED字符是受保护的;企图改变字体会产生一个EN_PROTECTED通知消息.yHeight字符高度,单位是twips(1/1440英寸或者1/20的打印机的打印点).yOffset字符偏移,单位是twips,从基线算起.如果该成员是正值,字符是下标,如果负值,字符是下标.crTextColor正文颜色.如果指定了CFE_AUTOCOLOR字符效果,这个值会被忽略.bCharSet字符集bPitchAndFamilyFontfamilyandpitch.szFaceName字体名字,是一个空字符结尾的字符数组._wPad2填充通过检查这个结构,你会发现我们可以改变正文效果(粗体,斜体,删除线,下划线),正文颜色(crTextColor)和字体外观/大小/字符集.值得注意的是CFE_RPOTECTED标志.具有该标志的正文会被标志上受保护标志,意味着当用户试图改变它时,EN_PROTECTED这个通知消息会被发送到父窗口.同时你可以允许该更改是是否可以进行.CHARFORMAT2增加更多的正文风格,象字体权值,间距,正文背景色,字距调整等等.如果你不需要这些额外的功能,只要使用CHARFORMAT即可.要设置正文格式,你必须考虑你想要该格式应用到的正文的范围.RichEdit控件引入了字符正文范围的概念.RichEdit分派给每个字符一个从0开始数字值:控件中的第一个字符具有数字ID值为0,第二个为1...等等。要说明一个正文范围,你必须提供给RichEdit控件两个数值:范围的第一个和最后一个字符的ID值。要跟EM_SETCHARFORMAT一起应用字符格式,你有最多3种选择:应用于控件中的所有正文。(SCF_ALL)应用于当前选定的正文。(SCF_SELECTION)应用于当前选定的一个单词。(SCF_WORD或者SCF_SELECTION)第一、二种情况是直观的,最后一个选择需要一点解释。如果当前选择只覆盖了词中的一个或多个字符但是不是整个词,指定SCF_WORD+SCF_SELECTION标志将正文格式应用于整个单词。即使没有当前选定,只有插入点(光标)位于单词中,第三种情况下仍然会将正文格式应用到整个单词中。要使用EM_SETCHARFORMAT,你需要填充CHARFORMAT(或者CHARFORMAT2)结构的结果成员。譬如,如果我们要设置正文颜色,需要如下一样填充CHARFORMAT结构:.data? cfCHARFORMAT<>.....code movcf.cbSize,sizeofcf movcf.dwMask,CFM_COLOR movcf.crTextColor,0FF0000h invokeSendMessage,hwndRichEdit,EM_SETCHARFORMAT,SCF_ALL,addrcf以上的代码片段设置RichEdit控件的正文颜色为纯蓝色。注意当EM_SETCHARFORMAT发生时,如果控件中没有正文,在这个消息之后键入的正文将会使用消息EM_SETCHARFORMAT中指定的正文格式。设置正文/保存正文对于那些经常使用Edit控件的人来说,你们肯定对使用WM_GETTEXT/WM_SETTEXT来设置/保存控制中的正文的方法很熟悉。这个方法对RichEdit仍然适用,但是如果文件很大的话这个方法不再是最有效的。Edit控件限制了正文长度,可以输入最多64K的正文。但是RichEdit控件可以接受比这个限制大的多的正文数据。要分配一个很大的内存块(譬如大约10MB)来接受来自来自WM_GETTEXT消息的正文是一件很麻烦的事.Richedit控件为此提供了一个新的方法,就是正文流(TextStreaming)。要设置RichEdit文本,你只需给RichEdit简单的提供一个回调函数的地址,当一切准备好时,RichEdit会调用回调函数,并将正文缓冲区的地址传递给它。回调函数会将要发送给RichEdit的数据填入缓冲区或者将缓冲区的数据读出,然后等待下一次调用自到操作完成。范例程序是流入(设置正文)和流出(取出正文)两者的例子。你将会发现这个方法更加有效:这个缓冲区是RichEdit控件自己提供的,因此数据被分成了几个大块。这个操作包括两条消息:EM_STREAMIN和EM_STREAMOUT。EM_STREAMIN和EM_STREAMOUT两者使用同一个语法:wParam==格式选项.SF_RTF数据是RTF格式。SF_TEXT数据是简单正文格式。SFF_PLAINRTF只有那些对所有语系都共有的关键词才流入。SFF_SELECTION如果指定这个标志,流操作的目标就是当前选定的正文。如果你将正文流入,当前正文就会被替换,如果是流出,则只有那些当前选定的正文才流出。如果没有指定这个标志,操作就会影响到控件中的所有正文。SF_UNICODE(RichEdit2.0或更高版本才提供)指定的是Unicode正文。lParam==指向一个EDITSTREAM结构,该结构定义如下:EDITSTREAMSTRUCT dwCookieDWORD? dwErrorDWORD? pfnCallbackDWORD?EDITSTREAMENDSdwCookie应用程序定义的数值,将会被传递给由pfnCallback成员说明的回调函数。通常地我们传递一些重要的参数值给回调函数,譬如流入/流出处理中使用到的文件句柄。dwError指示流入(读)或流出(写)操作的结果。0说明没有错误。非0值可以是EditStreamCallback函数的返回值或者说明控件遇到了错误。pfnCallback指向EditStreamCallback函数的指针,该函数是由用户定义,由RichEdit调用来传输数据的。RichEdit将数据分开多个部分,重复地调用该函数,一次一部分地进行数据传输。EditStream回调函数具有以下定义: EditStreamCallbackprotodwCookie:DWORD, pBuffer:DWORD, NumBytes:DWORD, pBytesTransferred:DWORD你必须在程序中按照以上原型来创建回调函数。然后将函数地址通过EDITSTREAM结构传递给EM_STREAMIN或者EM_STREAMOUT。对流入操作(设置RichEdit控件中的正文): dwCookie:应用程序定义的数值,通过EDITSTREAM结构传递给EM_STREAMIN。在这里我们几乎全部都是将用其内容来设置RichEdit正文的文件的句柄传给这个参数。 pBuffer:指向RichEdit提供的缓冲区。用来接受回调函数中提供的正文数据。 NumBytes:本次调用中你可以写入缓冲区(pBuffer)的最大正文字节数。你必须遵守这个限制,也就是说你发送的数据的大小可以比NumBytes指定要小,但是不能大于这个值。你可以将这个数值当作pBuffer缓冲区的大小。pBytesTransferred:指向一个双字(DWORD),你必须设置这个值来指示你实际上传输了多少字节数据到缓冲区。这个值通常跟NumBytes中的值是相等的.唯一的例外是当要传送的数据少于缓冲区提供的大小时,譬如到达文件尾时就是了。对流出操作(读出RichEdit控件的正文): dwCookie:跟流入操作相同.我们一般传递想要将数据写入的文件的句柄给这个参数。 pBuffer:指向由RichEdit提供的缓冲区,里面的是RichEdit的正文。要得到其大小,你必须检查NumBytes的知. NumBytes:pBuffer指向的缓冲区的的数据的大小。 pBytesTransferred:指向一个双字(DWORD),你必须设置这个值来指示你实际上从缓冲区里读出了多少字节数据。回调函数返回0说明操作成功,而且如果还有数据需要读/写的话,RichEdit控件会继续调用它。如果操作中发生了错误,而且你想停止操作的话,你可以返回一个非0值,这样RichEdit就会丢弃pBuffer指向的数据。错误/成功返回值会在EDITSTREAM的dwError成员中返回,你可以在SendMessage返回后检查流操作的错误/成功状态。.例子:下面的例子是一个简单的编辑器,你可以用来打开一个asm源文件,编辑它,然后保存。它使用了RichEdit控件2.0或者更高的版本..386.modelflat,stdcalloptioncasemap:noneinclude\masm32\include\windows.incinclude\masm32\include\user32.incinclude\masm32\include\comdlg32.incinclude\masm32\include\gdi32.incinclude\masm32\include\kernel32.incincludelib\masm32\lib\gdi32.libincludelib\masm32\lib\comdlg32.libincludelib\masm32\lib\user32.libincludelib\masm32\lib\kernel32.libWinMainproto:DWORD,:DWORD,:DWORD,:DWORD.constIDR_MAINMENUequ101IDM_OPENequ40001IDM_SAVEequ40002IDM_CLOSEequ40003IDM_SAVEASequ40004IDM_EXITequ40005IDM_COPYequ40006IDM_CUTequ40007IDM_PASTEequ40008IDM_DELETEequ40009IDM_SELECTALLequ40010IDM_OPTION equ40011IDM_UNDO equ40012IDM_REDO equ40013IDD_OPTIONDLGequ101IDC_BACKCOLORBOXequ1000IDC_TEXTCOLORBOXequ1001RichEditID equ300.dataClassNamedb"IczEditClass",0AppNamedb"IczEditversion1.0",0RichEditDLLdb"riched20.dll",0RichEditClassdb"RichEdit20A",0NoRichEditdb"Cannotfindriched20.dll",0ASMFilterString db"ASMSourcecode(*.asm)",0,"*.asm",0 db"AllFiles(*.*)",0,"*.*",0,0OpenFileFaildb"Cannotopenthefile",0WannaSavedb"Thedatainthecontrolismodified.Wanttosaveit?",0FileOpenedddFALSEBackgroundColordd0FFFFFFh ;缺省为白色TextColordd0 ;缺省为黑色.data?hInstancedd?hRichEditdd?hwndRichEditdd?FileNamedb256dup(?)AlternateFileNamedb256dup(?)CustomColorsdd16dup(?).codestart: invokeGetModuleHandle,NULL movhInstance,eax invokeLoadLibrary,addrRichEditDLL .ifeax!=0 movhRichEdit,eax invokeWinMain,hInstance,0,0,SW_SHOWDEFAULT invokeFreeLibrary,hRichEdit .else invokeMessageBox,0,addrNoRichEdit,addrAppName,MB_OKorMB_ICONERROR .endif invokeExitProcess,eax WinMainprochInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD LOCALwc:WNDCLASSEX LOCALmsg:MSG LOCALhwnd:DWORD movwc.cbSize,SIZEOFWNDCLASSEX movwc.style,CS_HREDRAWorCS_VREDRAW movwc.lpfnWndProc,OFFSETWndProc movwc.cbClsExtra,NULL movwc.cbWndExtra,NULL pushhInst popwc.hInstance movwc.hbrBackground,COLOR_WINDOW+1 movwc.lpszMenuName,IDR_MAINMENU movwc.lpszClassName,OFFSETClassName invokeLoadIcon,NULL,IDI_APPLICATION movwc.hIcon,eax movwc.hIconSm,eax invokeLoadCursor,NULL,IDC_ARROW movwc.hCursor,eax invokeRegisterClassEx,addrwc INVOKECreateWindowEx,NULL,ADDRClassName,ADDRAppName,\WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\hInst,NULL movhwnd,eax invokeShowWindow,hwnd,SW_SHOWNORMAL invokeUpdateWindow,hwnd .whileTRUE invokeGetMessage,ADDRmsg,0,0,0 .break.if(!eax) invokeTranslateMessage,ADDRmsg invokeDispatchMessage,ADDRmsg .endw moveax,msg.wParam retWinMainendpStreamInProcprochFile:DWORD,pBuffer:DWORD,NumBytes:DWORD,pBytesRead:DWORD invokeReadFile,hFile,pBuffer,NumBytes,pBytesRead,0 xoreax,1 retStreamInProcendpStreamOutProcprochFile:DWORD,pBuffer:DWORD,NumBytes:DWORD,pBytesWritten:DWORD invokeWriteFile,hFile,pBuffer,NumBytes,pBytesWritten,0 xoreax,1 retStreamOutProcendpCheckModifyStateprochWnd:DWORD invokeSendMessage,hwndRichEdit,EM_GETMODIFY,0,0 .ifeax!=0 invokeMessageBox,hWnd,addrWannaSave,addrAppName,MB_YESNOCANCEL .ifeax==IDYES invokeSendMessage,hWnd,WM_COMMAND,IDM_SAVE,0 .elseifeax==IDCANCEL moveax,FALSE ret .endif .endif moveax,TRUE retCheckModifyStateendpSetColorproc LOCALcfm:CHARFORMAT invokeSendMessage,hwndRichEdit,EM_SETBKGNDCOLOR,0,BackgroundColor invokeRtlZeroMemory,addrcfm,sizeofcfm movcfm.cbSize,sizeofcfm movcfm.dwMask,CFM_COLOR pushTextColor popcfm.crTextColor invokeSendMessage,hwndRichEdit,EM_SETCHARFORMAT,SCF_ALL,addrcfm retSetColorendpOptionProcprochWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD LOCALclr:CHOOSECOLOR .ifuMsg==WM_INITDIALOG .elseifuMsg==WM_COMMAND moveax,wParam shreax,16 .ifax==BN_CLICKED moveax,wParam .ifax==IDCANCEL invokeSendMessage,hWnd,WM_CLOSE,0,0 .elseifax==IDC_BACKCOLORBOX invokeRtlZeroMemory,addrclr,sizeofclr movclr.lStructSize,sizeofclr pushhWnd popclr.hwndOwner pushhInstance popclr.hInstance pushBackgroundColor popclr.rgbResult movclr.lpCustColors,offsetCustomColors movclr.Flags,CC_ANYCOLORorCC_RGBINIT invokeChooseColor,addrclr .ifeax!=0 pushclr.rgbResult popBackgroundColor invokeGetDlgItem,hWnd,IDC_BACKCOLORBOX invokeInvalidateRect,eax,0,TRUE .endif .elseifax==IDC_TEXTCOLORBOX invokeRtlZeroMemory,addrclr,sizeofclr movclr.lStructSize,sizeofclr pushhWnd popclr.hwndOwner pushhInstance popclr.hInstance pushTextColor popclr.rgbResult movclr.lpCustColors,offsetCustomColors movclr.Flags,CC_ANYCOLORorCC_RGBINIT invokeChooseColor,addrclr .ifeax!=0 pushclr.rgbResult popTextColor invokeGetDlgItem,hWnd,IDC_TEXTCOLORBOX invokeInvalidateRect,eax,0,TRUE .endif .elseifax==IDOK ;================================================================================== ;保存RichEdit控件的修改状态,因为更改正文颜色时改变了RichEdit控件的修改状态。 ; ;================================================================================== invokeSendMessage,hwndRichEdit,EM_GETMODIFY,0,0 pusheax invokeSetColor popeax invokeSendMessage,hwndRichEdit,EM_SETMODIFY,eax,0 invokeEndDialog,hWnd,0 .endif .endif .elseifuMsg==WM_CTLCOLORSTATIC invokeGetDlgItem,hWnd,IDC_BACKCOLORBOX .ifeax==lParam invokeCreateSolidBrush,BackgroundColor ret .else invokeGetDlgItem,hWnd,IDC_TEXTCOLORBOX .ifeax==lParam invokeCreateSolidBrush,TextColor ret .endif .endif moveax,FALSE ret .elseifuMsg==WM_CLOSE invokeEndDialog,hWnd,0 .else moveax,FALSE ret .endif moveax,TRUE retOptionProcendpWndProcprochWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD LOCALchrg:CHARRANGE LOCALofn:OPENFILENAME LOCALbuffer[256]:BYTE LOCALeditstream:EDITSTREAM LOCALhFile:DWORD .ifuMsg==WM_CREATE invokeCreateWindowEx,WS_EX_CLIENTEDGE,addrRichEditClass,0,WS_CHILDorWS_VISIBLEorES_MULTILINEorWS_VSCROLLorWS_HSCROLLorES_NOHIDESEL,\ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hWnd,RichEditID,hInstance,0 movhwndRichEdit,eax ;============================================================= ;设置正文长度限制,缺省是64K ;============================================================= invokeSendMessage,hwndRichEdit,EM_LIMITTEXT,-1,0 ;============================================================= ;Setthedefaulttext/backgroundcolor ;============================================================= invokeSetColor invokeSendMessage,hwndRichEdit,EM_SETMODIFY,FALSE,0 invokeSendMessage,hwndRichEdit,EM_EMPTYUNDOBUFFER,0,0 .elseifuMsg==WM_INITMENUPOPUP moveax,lParam .ifax==0 ;filemenu .ifFileOpened==TRUE ;afileisalreadyopened invokeEnableMenuItem,wParam,IDM_OPEN,MF_GRAYED invokeEnableMenuItem,wParam,IDM_CLOSE,MF_ENABLED invokeEnableMenuItem,wParam,IDM_SAVE,MF_ENABLED invokeEnableMenuItem,wParam,IDM_SAVEAS,MF_ENABLED .else invokeEnableMenuItem,wParam,IDM_OPEN,MF_ENABLED invokeEnableMenuItem,wParam,IDM_CLOSE,MF_GRAYED invokeEnableMenuItem,wParam,IDM_SAVE,MF_GRAYED invokeEnableMenuItem,wParam,IDM_SAVEAS,MF_GRAYED .endif .elseifax==1 ;edit菜单 ;============================================================================= ;检查剪贴板里是否有正文,如果有的话我们就使能Paste菜单项。 ;============================================================================= invokeSendMessage,hwndRichEdit,EM_CANPASTE,CF_TEXT,0 .ifeax==0 ;notextintheclipboard invokeEnableMenuItem,wParam,IDM_PASTE,MF_GRAYED .else invokeEnableMenuItem,wParam,IDM_PASTE,MF_ENABLED .endif ;========================================================== ;检查Undo队列时是否为空 ;========================================================== invokeSendMessage,hwndRichEdit,EM_CANUNDO,0,0 .ifeax==0 invokeEnableMenuItem,wParam,IDM_UNDO,MF_GRAYED .else invokeEnableMenuItem,wParam,IDM_UNDO,MF_ENABLED .endif ;========================================================= ;检查Redo队列时是否为空 ;========================================================= invokeSendMessage,hwndRichEdit,EM_CANREDO,0,0 .ifeax==0 invokeEnableMenuItem,wParam,IDM_REDO,MF_GRAYED .else invokeEnableMenuItem,wParam,IDM_REDO,MF_ENABLED .endif ;========================================================= ;检查RichEdit控件中是否有当前选定正文,有的话就使能 ;cut/copy/delete菜单项。 ;========================================================= invokeSendMessage,hwndRichEdit,EM_EXGETSEL,0,addrchrg moveax,chrg.cpMin .ifeax==chrg.cpMax ;没有当前选定 invokeEnableMenuItem,wParam,IDM_COPY,MF_GRAYED invokeEnableMenuItem,wParam,IDM_CUT,MF_GRAYED invokeEnableMenuItem,wParam,IDM_DELETE,MF_GRAYED .else invokeEnableMenuItem,wParam,IDM_COPY,MF_ENABLED invokeEnableMenuItem,wParam,IDM_CUT,MF_ENABLED invokeEnableMenuItem,wParam,IDM_DELETE,MF_ENABLED .endif .endif .elseifuMsg==WM_COMMAND .iflParam==0 ;命令菜单 moveax,wParam .ifax==IDM_OPEN invokeRtlZeroMemory,addrofn,sizeofofn movofn.lStructSize,sizeofofn pushhWnd popofn.hwndOwner pushhInstance popofn.hInstance movofn.lpstrFilter,offsetASMFilterString movofn.lpstrFile,offsetFileName movbyteptr[FileName],0 movofn.nMaxFile,sizeofFileName movofn.Flags,OFN_FILEMUSTEXISTorOFN_HIDEREADONLYorOFN_PATHMUSTEXIST invokeGetOpenFileName,addrofn .ifeax!=0 invokeCreateFile,addrFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .ifeax!=INVALID_HANDLE_VALUE movhFile,eax ;================================================================ ;将正文流入RichEdit控件。 ;================================================================ moveditstream.dwCookie,eax moveditstream.pfnCallback,offsetStreamInProc invokeSendMessage,hwndRichEdit,EM_STREAMIN,SF_TEXT,addreditstream ;========================================================== ;初始化修改状态为FALSE ;========================================================== invokeSendMessage,hwndRichEdit,EM_SETMODIFY,FALSE,0 invokeCloseHandle,hFile movFileOpened,TRUE .else invokeMessageBox,hWnd,addrOpenFileFail,addrAppName,MB_OKorMB_ICONERROR .endif .endif .elseifax==IDM_CLOSE invokeCheckModifyState,hWnd .ifeax==TRUE invokeSetWindowText,hwndRichEdit,0 movFileOpened,FALSE .endif .elseifax==IDM_SAVE invokeCreateFile,addrFileName,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0 .ifeax!=INVALID_HANDLE_VALUE@@: movhFile,eax ;================================================================ ;将RichEdit中的正文流出到文件中。 ;================================================================ moveditstream.dwCookie,eax moveditstream.pfnCallback,offsetStreamOutProc invokeSendMessage,hwndRichEdit,EM_STREAMOUT,SF_TEXT,addreditstream ;========================================================== ;初始化修改状态为FALSE ;========================================================== invokeSendMessage,hwndRichEdit,EM_SETMODIFY,FALSE,0 invokeCloseHandle,hFile .else invokeMessageBox,hWnd,addrOpenFileFail,addrAppName,MB_OKorMB_ICONERROR .endif .elseifax==IDM_COPY invokeSendMessage,hwndRichEdit,WM_COPY,0,0 .elseifax==IDM_CUT invokeSendMessage,hwndRichEdit,WM_CUT,0,0 .elseifax==IDM_PASTE invokeSendMessage,hwndRichEdit,WM_PASTE,0,0 .elseifax==IDM_DELETE invokeSendMessage,hwndRichEdit,EM_REPLACESEL,TRUE,0 .elseifax==IDM_SELECTALL movchrg.cpMin,0 movchrg.cpMax,-1 invokeSendMessage,hwndRichEdit,EM_EXSETSEL,0,addrchrg .elseifax==IDM_UNDO invokeSendMessage,hwndRichEdit,EM_UNDO,0,0 .elseifax==IDM_REDO invokeSendMessage,hwndRichEdit,EM_REDO,0,0 .elseifax==IDM_OPTION invokeDialogBoxParam,hInstance,IDD_OPTIONDLG,hWnd,addrOptionProc,0 .elseifax==IDM_SAVEAS invokeRtlZeroMemory,addrofn,sizeofofn movofn.lStructSize,sizeofofn pushhWnd popofn.hwndOwner pushhInstance popofn.hInstance movofn.lpstrFilter,offsetASMFilterString movofn.lpstrFile,offsetAlternateFileName movbyteptr[AlternateFileName],0 movofn.nMaxFile,sizeofAlternateFileName movofn.Flags,OFN_FILEMUSTEXISTorOFN_HIDEREADONLYorOFN_PATHMUSTEXIST invokeGetSaveFileName,addrofn .ifeax!=0 invokeCreateFile,addrAlternateFileName,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0 .ifeax!=INVALID_HANDLE_VALUE jmp@B .endif .endif .elseifax==IDM_EXIT invokeSendMessage,hWnd,WM_CLOSE,0,0 .endif .endif .elseifuMsg==WM_CLOSE invokeCheckModifyState,hWnd .ifeax==TRUE invokeDestroyWindow,hWnd .endif .elseifuMsg==WM_SIZE moveax,lParam movedx,eax andeax,0FFFFh shredx,16 invokeMoveWindow,hwndRichEdit,0,0,eax,edx,TRUE .elseifuMsg==WM_DESTROY invokePostQuitMessage,NULL .else invokeDefWindowProc,hWnd,uMsg,wParam,lParam ret .endif xoreax,eax retWndProcendpendstart;===================================================================;资源文件;===================================================================#include"resource.h"#defineIDR_MAINMENU101#defineIDD_OPTIONDLG101#defineIDC_BACKCOLORBOX1000#defineIDC_TEXTCOLORBOX1001#defineIDM_OPEN40001#defineIDM_SAVE40002#defineIDM_CLOSE40003#defineIDM_SAVEAS40004#defineIDM_EXIT40005#defineIDM_COPY40006#defineIDM_CUT40007#defineIDM_PASTE40008#defineIDM_DELETE40009#defineIDM_SELECTALL40010#defineIDM_OPTION40011#defineIDM_UNDO40012#defineIDM_REDO40013IDR_MAINMENUMENUDISCARDABLEBEGINPOPUP"&File"BEGINMENUITEM"&Open",IDM_OPENMENUITEM"&Close",IDM_CLOSEMENUITEM"&Save",IDM_SAVEMENUITEM"Save&As",IDM_SAVEASMENUITEMSEPARATORMENUITEM"E&xit",IDM_EXITENDPOPUP"&Edit"BEGINMENUITEM"&Undo",IDM_UNDOMENUITEM"&Redo",IDM_REDOMENUITEM"&Copy",IDM_COPYMENUITEM"C&ut",IDM_CUTMENUITEM"&Paste",IDM_PASTEMENUITEMSEPARATORMENUITEM"&Delete",IDM_DELETEMENUITEMSEPARATORMENUITEM"Select&All",IDM_SELECTALLENDMENUITEM"Options",IDM_OPTIONENDIDD_OPTIONDLGDIALOGDISCARDABLE0,0,183,54STYLEDS_MODALFRAME|WS_POPUP|WS_VISIBLE|WS_CAPTION|WS_SYSMENU|DS_CENTERCAPTION"Options"FONT8,"MSSansSerif"BEGINDEFPUSHBUTTON"OK",IDOK,137,7,39,14PUSHBUTTON"Cancel",IDCANCEL,137,25,39,14GROUPBOX"",IDC_STATIC,5,0,124,49LTEXT"BackgroundColor:",IDC_STATIC,20,14,60,8LTEXT"",IDC_BACKCOLORBOX,85,11,28,14,SS_NOTIFY|WS_BORDERLTEXT"TextColor:",IDC_STATIC,20,33,35,8LTEXT"",IDC_TEXTCOLORBOX,85,29,28,14,SS_NOTIFY|WS_BORDEREND分析:例子程序首先载入RichEditDLL,在这里是riched20.dll.如果DLL载入失败,就返回Windows.invokeLoadLibrary,addrRichEditDLL.ifeax!=0 movhRichEdit,eax invokeWinMain,hInstance,0,0,SW_SHOWDEFAULT invokeFreeLibrary,hRichEdit.else invokeMessageBox,0,addrNoRichEdit,addrAppName,MB_OKorMB_ICONERROR.endifinvokeExitProcess,eax成功载入DLL后,我们继续创建一个常规窗口,作为RichEdit的父窗口。在WM_CREATE处理函数里,我们创建一个RichEdit控件: invokeCreateWindowEx,WS_EX_CLIENTEDGE,addrRichEditClass,0,WS_CHILDorWS_VISIBLEorES_MULTILINEorWS_VSCROLLorWS_HSCROLLorES_NOHIDESEL,\ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hWnd,RichEditID,hInstance,0 movhwndRichEdit,eax注意在这里我们指定了ES_MULTILINE风格,否则创建的会是一个单行的控件。 invokeSendMessage,hwndRichEdit,EM_LIMITTEXT,-1,0创建了RichEdit控件之后,我们必须设置新的正文大小。缺省时,RichEdit控件具有64K的正文大小限制,跟简单的多行Edit控件相同。我们需要扩展这个限制,允许用来操作更大的文件。在上一个代码行里,我们指定了大小为-1,大小总计为0FFFFFFFFh字节,是一个很大的数值了。invokeSetColor

下一步,我们设置正文/背景色。因为这个操作可以在程序中的其他部分执行,我把这些代码放到一个叫SetColor的函数里。SetColorproc LOCALcfm:CHARFORMAT invokeSendMessage,hwndRichEdit,EM_SETBKGNDCOLOR,0,BackgroundColor设置RichEdit控件的背景色是一个很简单的操作:只需发送EM_SETBKGNDCOLOR信息给RIchEdit控件就行了。(如果你使用多行Edit控件,你必须处理WM_CTLCOLOREDIT消息)。缺省的背景色是白色的。 invokeRtlZeroMemory,addrcfm,sizeofcfm movcfm.cbSize,sizeofcfm movcfm.dwMask,CFM_COLOR pushTextColor popcfm.crTextColor设置好背景色之后,我们填充CHARFORMAT的成员,以便用来设置设置正文颜色。应该注意的是我们使用该结构的大小来填充cbSize成员,这样RichEdit控件就知道我们发送的是CHARFORMAT,而不是CHARFORMAT2。dwMask只使用了一个CFM_COLOR标志,因为我们只想设置正文颜色,同时往crTextColor里填入我们想要的正文颜色值. invokeSendMessage,hwndRichEdit,EM_SETCHARFORMAT,SCF_ALL,addrcfm retSetColorendp设置好颜色后,你必须要清空Undo缓冲区,因为更改正文/背景颜色的操作是可撤消的(Undo-able),更改颜色时在缓冲区里留下了Undo信息。我们可以发送EM_EMPTYUNDOBUFFER消息来实现这个操作。 invokeSendMessage,hwndRichEdit,EM_EMPTYUNDOBUFFER,0,0填充好CHARFORMAT结构,我们发送EM_SETCHARFORMAT消息给RichEdit控件,在wParam中指定SCF_ALL标志,说明我们想把正文格式应用于控件中的所有正文。注意在我们第一次创建RichEdit控件时,我们没有指定它的大小/位置。这是因为我们想它覆盖父窗口的全部客户区。当父窗口大小改变时,我们就跟着改变RichEdit控件的大小。 .elseifuMsg==WM_SIZE moveax,lParam movedx,eax andeax,0FFFFh shredx,16 invokeMoveWindow,hwndRichEdit,0,0,eax,edx,TRUE在上面的程序片段,我们使用了在lParam中的客户区的新尺寸,通过MoveWindow来改变RichEdit的大小。当用户点击文件File/Edit菜单条时,我们处理WM_INITPOPUPMENU消息,因此我们可以在显示子菜单给用户之前准备好各个子菜单项的状态。譬如,如果已经有一个文件在RichEdit控件中打开了,我们想禁止Open菜单项同时使能其他的菜单项。对于这种情况下的File菜单条,我们使用变量FileOpened来作为标志表示是否有一个文件已经打开了。如果这个变量是TRUE值,我们知道已经有一个文件被打开了。 .elseifuMsg==WM_INITMENUPOPUP moveax,lParam .ifax==0 ;file菜单 .ifFileOpened==TRUE ;已经打开了一个文件 invokeEnableMenuItem,wParam,IDM_OPEN,MF_GRAYED invokeEnableMenuItem,wParam,IDM_CLOSE,MF_ENABLED invokeEnableMenuItem,wParam,IDM_SAVE,MF_ENABLED invokeEnableMenuItem,wParam,IDM_SAVEAS,MF_ENABLED .else invokeEnableMenuItem,wParam,IDM_OPEN,MF_ENABLED invokeEnableMenuItem,wParam,IDM_CLOSE,MF_GRAYED invokeEnableMenuItem,wParam,IDM_SAVE,MF_GRAYED invokeEnableMenuItem,wParam,IDM_SAVEAS,MF_GRAYED .endif正如你所见的,如果有一个文件已经打开了,我们将Open菜单项变灰禁止并将其他菜单项都使能。跟TRUE值相反的是FileOpened值为FALSE.在这种情况下的EDIT菜单条我们需要先检查RichEdit控件/剪贴板的状态。 invokeSendMessage,hwndRichEdit,EM_CANPASTE,CF_TEXT,0 .ifeax==0 ;剪贴板里没有正文 invokeEnableMenuItem,wParam,IDM_PASTE,MF_GRAYED .else invokeEnableMenuItem,wParam,IDM_PASTE,MF_ENABLED .endif我们首先发送EM_CANPASTE消息,来检查剪贴板里是否存在可用的正文。如果有的话,SendMessage返回TRUE,我们就将Paste菜单项使能。如果没有的话,我们将该菜单项变灰禁止。 invokeSendMessage,hwndRichEdit,EM_CANUNDO,0,0 .ifeax==0 invokeEnableMenuItem,wParam,IDM_UNDO,MF_GRAYED .else invokeEnableMenuItem,wParam,IDM_UNDO,MF_ENABLED .endif跟着,我们通过发送EM_CANUNDO消息来检查Undo缓冲区是否为空,如果不空,SendMessage返回TRUE,我们就使能Undo菜单项。 invokeSendMessage,hwndRichEdit,EM_CANREDO,0,0 .ifeax==0 invokeEnableMenuItem,wParam,IDM_REDO,MF_GRAYED .

温馨提示

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

最新文档

评论

0/150

提交评论