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

📄 tut35.html

📁 WINDOWS程序员使用指南--汇编基础
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<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,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

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

.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 3.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		; default to white
TextColor dd 0		; default to black
WordFileName db "\wordfile.txt",0
ASMSection db "ASSEMBLY",0
C1Key db "C1",0
C2Key db "C2",0
C3Key db "C3",0
C4Key db "C4",0
C5Key db "C5",0
C6Key db "C6",0
C7Key db "C7",0
C8Key db "C8",0
C9Key db "C9",0
C10Key db "C10",0
ZeroString db 0
ASMColorArray 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 box
hAccel dd ?
hMainHeap dd ?		; heap handle
OldWndProc dd ?
RichEditVersion dd ?

.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 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
	ret
WinMain endp

StreamInProc proc hFile:DWORD,pBuffer:DWORD, NumBytes:DWORD, pBytesRead:DWORD
	invoke ReadFile,hFile,pBuffer,NumBytes,pBytesRead,0
	xor eax,1
	ret
StreamInProc endp

StreamOutProc proc hFile:DWORD,pBuffer:DWORD, NumBytes:DWORD, pBytesWritten:DWORD
	invoke WriteFile,hFile,pBuffer,NumBytes,pBytesWritten,0
	xor eax,1
	ret
StreamOutProc endp

CheckModifyState 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
	ret
CheckModifyState endp

SetColor 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
	ret
SetColor endp

OptionProc 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

⌨️ 快捷键说明

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