庞大资源库的计算机教程网站!
设为首页
加入收藏
总编信箱
投稿或申请专栏请先 [登 陆]
首页 操作系统 程序设计 图形图像 媒体动画 机械电子 WEB开发 数 据 库 办公系列 路由技术 网络原理 网络应用
认证考试 安全技术
首页>安全技术>黑客攻防>黑客编程>正文
资料搜索
Google搜索
Google
返回上级列表

推荐文章

快速保存网页中所有图片的方法
Windows中让光驱巧妙“隐身”技
防范非法用户入侵Win 2000/XP系
两款比较典型的ASP木马防范方法
有关表格边框的css语法整理
Windows XP中可以被禁用的服务
SQL Server导出导入数据方法
Javascript所有对象的属性的获
网页(HTML)中的特殊字符
与篮球共舞,尽显模式本色
QQ病毒的手工清除方法
Photoshop为极品美女打造性感睫
天衣无缝:IIS与PHP水火也相容
SQL Server存储过程编写和优化

Win32教程35-RichEdit控件.语法高亮显示 一

 作者:本站收集   日期:2005-5-24
字号选择〖 〗/ 双击滚屏 单击停止   
  读这篇教程之前先提醒你,这是一个复杂的主题:不适合初学者。这是最后一篇RichEdit 控件教程
理论
   语法高亮显示对那些编写文本编辑器的人来说是一个热点主题。最好的解决方法(我自己认为的)是编写一个定制的Edit控件,这也是很多商业软件所使用的方法。然而,对于那些没什么时间来编写这么一个控件的人来说,次策就是改写现有的控件使之符合我们的需要。

   让我们看一看,到底 RichEdit 控件提供了什么功能来帮助我们实现语法高亮。现在我应该声明,下面的方法不是一个“正确”方法:我只是给你们指出那些缺陷。 RichEdit 控件提供了EM_SETCHARFORMAT 消息,是你可以用来改变正文颜色。乍一看,这个消息好象是一个完美的解决方法(我之所以知道是因为我也是其中的一个受骗者)。然而靠近看看,将会发现有几个不合意的地方:

EM_SETCHARFORMAT 仅仅对选定的正文或者控件中所有的正文有影响。如果你想改变正文颜色(高亮显示某一个特定的词),你必须先选定它。
EM_SETCHARFORMAT 执行速度很慢。

   RichEdit 控件中的插入点位置处理也有一点问题。

   通过上面的讨论,你可以看到使用 EM_SETCHARFORMAT 是一个错误的选择,我会给你演示 "相当正确" 的选择。

   我现在使用的方法是“即时语法高亮”,我只高亮显示可见部分的正文。因此高亮显示的速度跟文件的大小根本是无关的。无论是多大的文件,在某一时刻只有一小部分是可见的。

   怎么样实现?答案很简单:

1.子类化RichEdit控件并在你自己的窗口处理函数中处理 WM_PAINT 消息。
2.当收到 WM_PAINT 消息时,它调用RichEdit控件原来的窗口过程,让它正常地更新屏幕。
3.之后,我们将要高亮显示的词用不同的颜色来覆盖掉。

   当然了,路也不是这么容易走的:仍然有两个次要的问题需要矫正,不过上面的方法工作起来很好。显示速度令人很满意。

   现在让我们集中在细节上。子类化处理是很简单的,不需要很多注意力。真正复杂的部分是:我们必须找到一个快速的方法来搜索那些需要高亮的词。更复杂的那些在某个注释块里的 不 需要高亮显示的词。

   我使用的方法可能不是最好的,但是它工作的很好。我敢肯定你可以找到更快的方法。不管怎么说,先看看我下面的方法:

   我创建一个有256元素的双字(DWORD)数组,全部初始化为0。每一个元素对应一个可能的 ASCII 字符,数组名叫 ASMSyntaxArray。例如,第21个元素代表ASCII 20h (空格字符)。我将他们作为快速查询表使用:譬如,假定我有一个词 "include",我从词中分离出第一个字符 (i) ,并以响应索引查找数组。如果该元素为0,我就立刻知道需要高亮的词是没有以 "i" 开头的。如果该元素非0,它就包含一个指针,指向一个 WORDINFO 结构的链表。里面包含了需要高亮词的信息。

   我读取需要高亮显示的词,并为每个词创建一个 WORDINFO 结构。

WORDINFO struct
WordLen dd ? ; 词的长度,用来快速比较
pszWord dd ? ; 词的指针
pColor dd ? ; 用来高亮显示的颜色所在的DWORD的指针
NextLink dd ? ; 下一个 WORDINFO 结构
WORDINFO ends

   正如你所看到的,我使用词的长度来作为第二个快速比较方法。如果词中的第一个字符匹配后,我们下一个比较的是词的才长度。ASMSyntaxArray 中的每一个元素包含了一个指针,指向一个相关的WORDINFO 数组.例如,代表字符 "i" 的元素将会包含一个指向以"i"开头的词的链表。 pColor 成员指向一个DWORD,包含用来做高亮显示该词的颜色值。pszWord 指向要高亮显示的词。是小写形式的。

   链表的内存是从堆(heap)中分配的,速度快,容易清除,也就是说根本不用清楚。
   高亮词列表保存在文件 "wordfile.txt"中,我通过 GetPrivateProfileString API 函数来访问。我提供了多达10种不同的语法颜色,从 C1 到 C10。颜色数组名叫 ASMColorArray。每一个 WORDINFO 结构的 pColor 成员都指向 ASMColorArray 中的某一个元素。因此闲时很容易改变语法颜色:你只需要改变 ASMColorArray 中的元素的值,这样所有使用那种颜色高亮的词就立刻使用新颜色显示。

例子
.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 ? ; 词的长度:用来进行快速比较
pszWord dd ? ; 词的指针
pColor dd ? ; 指向某个DWORD,里面包含用来高亮显示词的颜色值。
NextLink dd ? ; 指向下一个 WORDINFO 结构
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 ; 缺省为白色
TextColor dd 0 ; 缺省为黑色
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 ? ; 搜索/替换对话框的句柄
hAccel dd ?
hMainHeap dd ? ; 堆的句柄
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
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
ret
OptionProc endp

SearchProc 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
.if eax!=findtext.chrg.cpMax
push findtext.chrg.cpMax
pop findtext.chrg.cpMin
.endif
mov findtext.chrg.cpMax,-1
.else
mov findtext.chrg.cpMax,0
.endif
invoke IsDlgButtonChecked,hWnd,IDC_MATCHCASE
.if eax==BST_CHECKED
or uFlags,FR_MATCHCASE
.endif
invoke IsDlgButtonChecked,hWnd,IDC_WHOLEWORD
.if eax==BST_CHECKED
or uFlags,FR_WHOLEWORD
.endif
mov findtext.lpstrText,offset FindBuffer
invoke SendMessage,hwndRichEdit,EM_FINDTEXTEX,\
uFlags,addr findtext
.if eax!=-1
invoke SendMessage,hwndRichEdit,\
EM_EXSETSEL,0,addr findtext.chrgText
.endif
.endif
.elseif ax==IDCANCEL
invoke SendMessage,hWnd,WM_CLOSE,0,0
.else
mov eax,FALSE
ret
.endif
.endif
.elseif uMsg==WM_CLOSE
mov hSearch,0
invoke EndDialog,hWnd,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
SearchProc endp

上一篇:Win32教程35-RichEdit控件.语法高亮显示 二    下一篇:Win32教程32-多文档界面(MDI) 下  
[发送给好友]  [关闭窗口]  [返回顶部]   转载请注明来源:www.it00.com   
特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。
责任编辑: 原点 投稿作者: 本站收集
信息来源: 网络 录入时间: 2005-5-24
关于我们 - 广告服务 - 版权申明 - 网站地图 - 联系方式 - 总编信箱 - 会员投稿