⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lion-tutorial35.htm

📁 内有一些代码
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<html><head><title>Iczelion's Win32 Assembly Tutorial 35: RichEdit Control: Syntax Hilighting</title><meta http-equiv="Content-Type" content="text/html; charset="></head><body bgcolor="#FFFFFF"><h1 align="center"><font face="Tahoma" color="#0000FF">Tutorial 35: RichEdit Control:   Syntax Hilighting</font></h1><p align="left"><font face="Tahoma" size="-1">Before reading this tutorial, let   me warn you that it's a complicated subject: not suited for a beginner. This   is the last in the richedit control tutorials.</font></p><p align="left"><font face="Tahoma" size="-1">Download <a href="files/tut35.zip">the   example</a>.</font></p><h3 align="left"><font face="Times New Roman, Times, serif" color="#0000FF">Theory</font></h3><p align="left"><font face="Tahoma" size="-1">Syntax hilighting is a subject of   hot debate for those writing text editors. The best method (in my opinion) is   to code a custom edit control and this is the approach taken by lots of commercial   softwares. However, for those of us who don't have time for coding such control,   the next best thing is to adapt the existing control to make it suit our need.</font></p><p align="left"><font face="Tahoma" size="-1">Let us take a look at what RichEdit   control provides to help us in implementing syntax hilighting. I should state   at this moment that the following method is not the &quot;correct&quot; path:   I just want to show you the pitfall that many fall for. RichEdit control provides   <font color="#006666"> <b>EM_SETCHARFORMAT</b></font> message that you can use   to change the color of the text. At first glance, this message seems to be the   perfect solution (I know because I was one of the victim). However, a closer   examination will show you several things that are undesirable:</font></p><ul>  <li><font face="Tahoma" size="-1"><b><font color="#006666">EM_SETCHARFORMAT</font></b>     only works for a text currently in selection or all text in the control. If     you want to change the text color (hilight) a certain word, you must first     select it.</font></li>  <li><font face="Tahoma" size="-1"><b><font color="#006666">EM_SETCHARFORMAT</font></b>     is very slow</font></li>  <li><font face="Tahoma" size="-1">It has a problem with the caret position in     the richedit control</font></li></ul><p><font face="Tahoma" size="-1">With the above discussion, you can see that using   <font color="#006666"> <b>EM_SETCHARFORMAT</b></font> is a wrong choice. I'll   show you the &quot;relatively correct&quot; choice.</font></p><p><font face="Tahoma" size="-1">The method I currently use is &quot;syntax hilighting   just-in-time&quot;. I'll hilight only the visible portion of text. Thus the   speed of the hilighting will not be related to the size of the file at all.   No matter how large the file, only a small portion of it is visible at one time.</font></p><p><font face="Tahoma" size="-1">How to do that? The answer is simple: </font></p><ol>  <li><font face="Tahoma" size="-1">subclass the richedit control and handle <font color="#006666"><b>WM_PAINT</b></font>     message within your own window procedure</font></li>  <li><font face="Tahoma" size="-1">When it receives <font color="#006666"><b>WM_PAINT</b></font>     message, it calls the original window procedure of the richedit control to     let it update the screen as usual.</font></li>  <li><font face="Tahoma" size="-1">After that, we overwrite the words to be hilighted     with different color</font></li></ol><p><font face="Tahoma" size="-1">Of course, the road is not that easy: there are   still a couple of minor things to fix but the above method works quite nicely.   The display speed is very satisfactory.</font></p><p><font face="Tahoma" size="-1">Now let's concentrate on the detail. The subclassing   process is simple and doesn't require much attention. The really complicated   part is when we have to find a fast way of searching for the words to be hilighted.   This is further complicated by the need <font color="#006666"><b>not</b></font>   to hilight any word within a comment block. </font></p><p><font face="Tahoma" size="-1">The method I use may not be the best but it works   ok. I'm sure you can find a faster way. Anyway, here it is:</font></p><ul>  <li><font face="Tahoma" size="-1">I create a 256 dword array, initialized to     0. Each dword corresponds to a possible ASCII character,named <font color="#0000CC"><b>ASMSyntaxArray</b></font>.     For example, the 21th dword represents the ascii 20h (space). I use them as     a fast lookup table: For example, if I have the word &quot;include&quot;,     I'll extract the first character (i) from the word and look up the dword at     the corresponding index. If that dword is 0, I know immediately that there     is no words to be hilighted starting with &quot;i&quot;. If the dword is non-zero,     it contains the pointer to the linked list of the <font color="#006666"><b>WORDINFO</b></font>     structure which contains the information about the word to be hilighted.</font></li>  <li><font face="Tahoma" size="-1">I read the words to be hilighted and create     a <font color="#006666"><b>WORDINFO</b></font> structure for each of them.</font></li></ul><pre><font face="Tahoma"><b>			WORDINFO struct 				WordLen dd ? 		; the length of the word: used as a quick comparison    				pszWord dd ? 	; pointer to the word 				pColor dd ? 		; point to the dword that contains the color used to hilite the word 				NextLink dd ? 		; point to the next WORDINFO structure 			WORDINFO ends </b></font></pre><blockquote>   <p><font face="Tahoma" size="-1">As you can see, I use the length of the word     as the second quick comparison. If the first character of the word matches,     we next compare its length to the available words. Each dword in <font color="#0000CC"><b>ASMSyntaxArray</b></font>     contains a pointer to the head of the associated <font color="#006666"><b>WORDINFO</b></font>     array. For example, the dword that represents the character &quot;i&quot;     will contain the pointer to the linked list of the words that begin with &quot;i&quot;.     <font color="#990099"> <b>pColor</b></font> member points to the dword that     contains the color value used to hilight the word. <font color="#990099"><b>pszWord</b></font>     points to the word to be hilighted, in lowercase.</font></p></blockquote><ul>  <li><font face="Tahoma" size="-1">The memory for the linked list is allocated     from the default heap so it's fast and easy to clean up, ie, no cleaning up     required at all.</font></li></ul><p><font face="Tahoma" size="-1">The word list is stored in a file named &quot;wordfile.txt&quot;   and I access it with <font color="#000099"><b>GetPrivateProfileString</b></font>   APIs. I provide as many as 10 different syntax coloring, starting from C1 to   C10. The color array is named <font color="#006666"><b>ASMColorArray</b></font>.   pColor member of each <font color="#006666"><b>WORDINFO</b></font> structure   points to one of the dwords in <font color="#006666"><b>ASMColorArray</b></font>.   Thus it is easy to change the syntax coloring on the fly: you just change the   dword in <font color="#006666"><b>ASMColorArray</b></font> and all words using   that color will use the new color immediately. </font></p><h3><font face="Times New Roman, Times, serif" color="#0000CC">Example</font></h3><pre><font face="Tahoma"><b>.386.model flat,stdcalloption casemap: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.libWinMain proto :DWORD,:DWORD,:DWORD,:DWORDWORDINFO struct	WordLen dd ?		; the length of the word: used as a quick comparison	pszWord dd ?		; pointer to the word	pColor dd ?		; point to the dword that contains the color used to hilite the word	NextLink dd ?		; point to the next WORDINFO structureWORDINFO ends.constIDR_MAINMENU                   equ 101IDM_OPEN                      equ  40001IDM_SAVE                       equ 40002IDM_CLOSE                      equ 40003IDM_SAVEAS                     equ 40004IDM_EXIT                       equ 40005IDM_COPY                      equ  40006IDM_CUT                       equ  40007IDM_PASTE                      equ 40008IDM_DELETE                     equ 40009IDM_SELECTALL                  equ 40010IDM_OPTION 			equ 40011IDM_UNDO			equ 40012IDM_REDO			equ 40013IDD_OPTIONDLG                  equ 101IDC_BACKCOLORBOX               equ 1000IDC_TEXTCOLORBOX               equ 1001IDR_MAINACCEL                 equ  105IDD_FINDDLG                    equ 102IDD_GOTODLG                    equ 103IDD_REPLACEDLG                 equ 104IDC_FINDEDIT                  equ  1000IDC_MATCHCASE                  equ 1001IDC_REPLACEEDIT                 equ 1001IDC_WHOLEWORD                  equ 1002IDC_DOWN                       equ 1003IDC_UP                       equ   1004IDC_LINENO                   equ   1005IDM_FIND                       equ 40014IDM_FINDNEXT                  equ  40015IDM_REPLACE                     equ 40016IDM_GOTOLINE                   equ 40017IDM_FINDPREV                  equ  40018RichEditID 			equ 300.dataClassName db "IczEditClass",0AppName  db "IczEdit version 3.0",0RichEditDLL db "riched20.dll",0RichEditClass db "RichEdit20A",0NoRichEdit db "Cannot find riched20.dll",0ASMFilterString 		db "ASM Source code (*.asm)",0,"*.asm",0				db "All Files (*.*)",0,"*.*",0,0OpenFileFail db "Cannot open the file",0WannaSave db "The data in the control is modified. Want to save it?",0FileOpened dd FALSEBackgroundColor dd 0FFFFFFh		; default to whiteTextColor dd 0		; default to blackWordFileName db "\wordfile.txt",0ASMSection db "ASSEMBLY",0C1Key db "C1",0C2Key db "C2",0C3Key db "C3",0C4Key db "C4",0C5Key db "C5",0C6Key db "C6",0C7Key db "C7",0C8Key db "C8",0C9Key db "C9",0C10Key db "C10",0ZeroString db 0ASMColorArray dd 0FF0000h,0805F50h,0FFh,666F00h,44F0h,5F8754h,4 dup(0FF0000h)CommentColor dd 808000h.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 <>ASMSyntaxArray dd 256 dup(?)hSearch dd ?		; handle to the search/replace dialog boxhAccel dd ?hMainHeap dd ?		; heap handleOldWndProc dd ?RichEditVersion dd ?.codestart:	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 GetProcessHeap		mov hMainHeap,eax		call FillHiliteInfo		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		.break .if (!eax)		invoke IsDialogMessage,hSearch,addr msg		.if eax==FALSE			invoke TranslateAccelerator,hwnd,hAccel,addr msg			.if eax==0				invoke TranslateMessage, ADDR msg				invoke DispatchMessage, ADDR msg			.endif		.endif	.endw	mov   eax,msg.wParam	retWinMain endpStreamInProc proc hFile:DWORD,pBuffer:DWORD, NumBytes:DWORD, pBytesRead:DWORD	invoke ReadFile,hFile,pBuffer,NumBytes,pBytesRead,0	xor eax,1	retStreamInProc endpStreamOutProc proc hFile:DWORD,pBuffer:DWORD, NumBytes:DWORD, pBytesWritten:DWORD	invoke WriteFile,hFile,pBuffer,NumBytes,pBytesWritten,0	xor eax,1	retStreamOutProc endpCheckModifyState proc hWnd:DWORD	invoke SendMessage,hwndRichEdit,EM_GETMODIFY,0,0	.if eax!=0		invoke MessageBox,hWnd,addr WannaSave,addr AppName,MB_YESNOCANCEL		.if eax==IDYES			invoke SendMessage,hWnd,WM_COMMAND,IDM_SAVE,0		.elseif eax==IDCANCEL			mov eax,FALSE			ret		.endif	.endif	mov eax,TRUE	retCheckModifyState endpSetColor proc	LOCAL cfm:CHARFORMAT		invoke SendMessage,hwndRichEdit,EM_SETBKGNDCOLOR,0,BackgroundColor	invoke RtlZeroMemory,addr cfm,sizeof cfm	mov cfm.cbSize,sizeof cfm	mov cfm.dwMask,CFM_COLOR	push TextColor	pop cfm.crTextColor	invoke SendMessage,hwndRichEdit,EM_SETCHARFORMAT,SCF_ALL,addr cfm	retSetColor endpOptionProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD	LOCAL clr:CHOOSECOLOR	.if uMsg==WM_INITDIALOG	.elseif uMsg==WM_COMMAND		mov eax,wParam		shr eax,16		.if ax==BN_CLICKED			mov eax,wParam			.if ax==IDCANCEL				invoke SendMessage,hWnd,WM_CLOSE,0,0			.elseif ax==IDC_BACKCOLORBOX				invoke RtlZeroMemory,addr clr,sizeof clr				mov clr.lStructSize,sizeof clr				push hWnd				pop clr.hwndOwner				push hInstance				pop clr.hInstance				push BackgroundColor				pop clr.rgbResult				mov clr.lpCustColors,offset CustomColors				mov clr.Flags,CC_ANYCOLOR or CC_RGBINIT				invoke ChooseColor,addr clr				.if eax!=0					push clr.rgbResult					pop BackgroundColor					invoke GetDlgItem,hWnd,IDC_BACKCOLORBOX					invoke InvalidateRect,eax,0,TRUE				.endif			.elseif ax==IDC_TEXTCOLORBOX				invoke RtlZeroMemory,addr clr,sizeof clr				mov clr.lStructSize,sizeof clr				push hWnd				pop clr.hwndOwner				push hInstance				pop clr.hInstance				push TextColor				pop clr.rgbResult				mov clr.lpCustColors,offset CustomColors				mov clr.Flags,CC_ANYCOLOR or CC_RGBINIT				invoke ChooseColor,addr clr				.if eax!=0					push clr.rgbResult					pop TextColor					invoke GetDlgItem,hWnd,IDC_TEXTCOLORBOX					invoke InvalidateRect,eax,0,TRUE				.endif			.elseif ax==IDOK				invoke SendMessage,hwndRichEdit,EM_GETMODIFY,0,0				push eax				invoke SetColor				pop eax				invoke SendMessage,hwndRichEdit,EM_SETMODIFY,eax,0				invoke EndDialog,hWnd,0			.endif		.endif	.elseif uMsg==WM_CTLCOLORSTATIC		invoke GetDlgItem,hWnd,IDC_BACKCOLORBOX		.if eax==lParam			invoke CreateSolidBrush,BackgroundColor						ret		.else			invoke GetDlgItem,hWnd,IDC_TEXTCOLORBOX			.if eax==lParam				invoke CreateSolidBrush,TextColor				ret			.endif		.endif		mov eax,FALSE		ret	.elseif uMsg==WM_CLOSE		invoke EndDialog,hWnd,0	.else		mov eax,FALSE		ret	.endif	mov eax,TRUE	retOptionProc endpSearchProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD	.if uMsg==WM_INITDIALOG		push hWnd		pop hSearch		invoke CheckRadioButton,hWnd,IDC_DOWN,IDC_UP,IDC_DOWN		invoke SendDlgItemMessage,hWnd,IDC_FINDEDIT,WM_SETTEXT,0,addr FindBuffer	.elseif uMsg==WM_COMMAND		mov eax,wParam		shr eax,16		.if ax==BN_CLICKED			mov eax,wParam			.if ax==IDOK				mov uFlags,0				invoke SendMessage,hwndRichEdit,EM_EXGETSEL,0,addr findtext.chrg				invoke GetDlgItemText,hWnd,IDC_FINDEDIT,addr FindBuffer,sizeof FindBuffer				.if eax!=0					invoke IsDlgButtonChecked,hWnd,IDC_DOWN					.if eax==BST_CHECKED						or uFlags,FR_DOWN						mov eax,findtext.chrg.cpMin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -