📄 richedit.asm
字号:
invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassEdit,NULL,
WS_CHILD OR WS_VISIBLE OR WS_VSCROLL OR WS_HSCROLL \
OR ES_MULTILINE or ES_NOHIDESEL,
0,40,300,100,
hWin,0,hInstance,NULL ; 创建子窗口,窗口类为RichEdit20A
mov hWinEdit,eax
invoke RegisterWindowMessage,addr szFindMessage
mov idFindMessage,eax
; 版本8新增,设置事件掩码,指定哪些通知消息将发送给它的父窗口
invoke SendMessage,hWinEdit,EM_SETEVENTMASK,0,ENM_CHANGE or ENM_SELCHANGE
invoke SetFocus,hWinEdit
ret
Init endp
; ---------------------------------------------
; 调整布局 WM_SIZE的消息处理程序
; ---------------------------------------------
AdjustLayout proc
local stRectWinMain:RECT
local stRectToolBar:RECT
local stRectStatusBar:RECT
local dwWidth,dwHeight ; RichEdit控件的宽度和高度
local dwToolBarHeight :DWORD
invoke SendMessage,hToolBar,TB_AUTOSIZE,0,0
invoke MoveWindow,hWinStatus,0,0,0,0,TRUE
invoke GetClientRect,hWinMain,addr stRectWinMain ; 以主窗口的左上角为参考点
mov eax, stRectWinMain.right
sub eax, stRectWinMain.left
mov dwWidth,eax ; 计算出客户区的宽度,也就是RichEdit控件的宽度
mov eax, stRectWinMain.bottom
sub eax, stRectWinMain.top
mov dwHeight, eax ; 此时dwHeight为客户区的高度
invoke GetWindowRect,hToolBar,addr stRectToolBar ; 以屏幕的左上角为参考点
mov eax, stRectToolBar.bottom
sub eax, stRectToolBar.top
mov dwToolBarHeight, eax ; 计算出工具栏的高度
sub dwHeight, eax ; 原客户区高度 - 工具栏高度
invoke GetWindowRect,hWinStatus,addr stRectStatusBar ; 取状态栏的的矩形区域
mov eax, stRectStatusBar.bottom
sub eax, stRectStatusBar.top
sub dwHeight, eax ; 原客户区高度 - 工具栏高度 - 状态栏高度
invoke MoveWindow,hWinEdit,stRectWinMain.left,dwToolBarHeight,
dwWidth,dwHeight,TRUE
ret
AdjustLayout endp
; ---------------------------------------------
; 在打开文件、新文件、退出系统等情况下,
; 询问否保存已修改的内容
; ---------------------------------------------
Confirmation proc
invoke SendMessage,hWinEdit,WM_GETTEXTLENGTH,0,0
cmp eax, 0
jne @F
ret
@@:
invoke SendMessage,hWinEdit,EM_GETMODIFY,0,0
cmp eax, 0
jne @F
ret
confirm db '编辑器中内容已改变, 保存吗 ?',0
@@:
invoke MessageBox,hWinMain,ADDR confirm,
ADDR szDisplayName,
MB_YESNOCANCEL or MB_ICONQUESTION
.if eax == IDYES
invoke SaveFile
.endif
ret
Confirmation endp
; ---------------------------------------------
; 打开一个文件
; ---------------------------------------------
OpenTextFile proc
LOCAL stOF:OPENFILENAME ; 文件结构变量
LOCAL stES:EDITSTREAM
invoke RtlZeroMemory,addr stOF,sizeof stOF ; 结构变量清0
mov stOF.lStructSize,sizeof stOF
push hWinMain
pop stOF.hwndOwner
mov stOF.lpstrFilter,offset szFilter ; 文件名筛选字符串
mov stOF.lpstrFile,offset szFileName ; 全路径的文件名缓冲区
mov stOF.nMaxFile,MAX_PATH ; 文件名缓冲区长度
mov stOF.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST
mov stOF.lpstrDefExt,offset szDefaultExt ; 默认扩展名
invoke GetOpenFileName,addr stOF ; 显示打开文件对话框
.if !eax ; 按打开文件对话框中的取消或关闭,返回值为0
ret ; 直接返回
.endif
invoke CreateFile,addr szFileName, ; 打开文件
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,0,
OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
.if eax == INVALID_HANDLE_VALUE ; 文件打开错误,给出提示后返回
invoke MessageBox,hWinMain,addr szErrOpenFile,NULL,MB_OK or MB_ICONSTOP
ret
.endif
push eax ; 暂存本次打开的文件句柄
; 判断是否在本次打开文件之前,已打开过文件,
; 若已打开过,则要关闭原来的文件
.if hFile
invoke CloseHandle,hFile
.endif
pop eax
mov hFile,eax ; 保存打开的文件句柄
mov stES.dwCookie, TRUE
mov stES.pfnCallback, offset ProcStream ; ProcStream是EM_STREAMIN消息的回调函数
; 该函数被反复调用,直到文件全部读入
invoke SendMessage,hWinEdit,EM_STREAMIN,SF_TEXT,addr stES
invoke SendMessage,hWinEdit,EM_SETMODIFY,FALSE,0
invoke SetFocus,hWinEdit
invoke DisplayStatusBarInfo
invoke DisplayFacet
ret
OpenTextFile endp
; ---------------------------------------------
; 保存文件
; ---------------------------------------------
SaveFile proc
LOCAL stES:EDITSTREAM
.if !hFile ; 使用保存之前,未打开过文件,执行另存为
invoke SaveFileAs
ret
.endif
invoke SetFilePointer,hFile,0,0,FILE_BEGIN ; 将文件指针移到文件头
mov stES.dwCookie, FALSE
mov stES.pfnCallback, offset ProcStream ; ProcStream是EM_STREAMIN消息的回调函数
; 该函数被反复调用,直到文件全部读入
invoke SendMessage,hWinEdit,EM_STREAMOUT,SF_TEXT,addr stES
invoke SendMessage,hWinEdit,EM_SETMODIFY,FALSE,0
invoke SetEndOfFile,hFile ; 设置文件结束
ret
SaveFile endp
; ---------------------------------------------
; 文件另存为
; ---------------------------------------------
SaveFileAs proc
LOCAL stOF :OPENFILENAME ; 文件结构变量
LOCAL stES:EDITSTREAM
.if hFile ;如果是打开了一个文件,有单击了"另存为",则先关闭前面的文件
invoke CloseHandle,hFile
.endif
invoke RtlZeroMemory,addr stOF,sizeof stOF ; 结构变量清0
mov stOF.lStructSize,sizeof stOF
push hWinMain
pop stOF.hwndOwner
mov stOF.lpstrFilter,offset szFilter ; 文件名筛选字符串
mov stOF.lpstrFile,offset szFileName ; 全路径的文件名缓冲区
mov stOF.nMaxFile,MAX_PATH ; 文件名缓冲区长度
mov stOF.Flags,OFN_OVERWRITEPROMPT
mov stOF.lpstrDefExt,offset szDefaultExt ; 默认扩展名
invoke GetSaveFileName,addr stOF ; 显示打开文件对话框
.if !eax ; 按另存为文件对话框中的取消或关闭,返回值为0
ret ; 直接返回
.endif
invoke CreateFile,addr szFileName, ; 创建文件
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,0,
CREATE_NEW,FILE_ATTRIBUTE_NORMAL,0
.if eax == INVALID_HANDLE_VALUE ; 文件打开错误,给出提示后返回
invoke MessageBox,hWinMain,addr szErrOpenFile,NULL,MB_OK or MB_ICONSTOP
ret
.endif
mov hFile, eax
mov stES.dwCookie, FALSE
mov stES.pfnCallback, offset ProcStream ; ProcStream是EM_STREAMIN消息的回调函数
; 该函数被反复调用,直到文件全部读入
invoke SendMessage,hWinEdit,EM_STREAMOUT,SF_TEXT,addr stES
invoke SendMessage,hWinEdit,EM_SETMODIFY,FALSE,0
ret
SaveFileAs endp
; ---------------------------------------------
; Richedit的流操作
; ---------------------------------------------
ProcStream proc uses ebx edi esi dwCookie,lpBuffer,dwBytes,lpBytes
.if dwCookie
invoke ReadFile,hFile,lpBuffer,dwBytes,lpBytes,0
.else
invoke WriteFile,hFile,lpBuffer,dwBytes,lpBytes,0
.endif
xor eax,eax
ret
ProcStream endp
; ---------------------------------------------
; 加载图标 LoadToolBar
; ---------------------------------------------
LoadToolBar proc hWin
; 使用系统的位图
invoke CreateToolbarEx, hWin, ; 创建工具栏
WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS or CCS_ADJUSTABLE,
0,0,HINST_COMMCTRL,IDB_STD_SMALL_COLOR,
offset lpButtons,14,0,0,0,0,sizeof TBBUTTON
mov hToolBar, eax
ret
LoadToolBar endp
; ---------------------------------------------
; 菜单及工具的灰化 DisplayFacet
; ---------------------------------------------
DisplayFacet proc
invoke SendMessage,hWinEdit,EM_GETMODIFY,0,0
.if eax
invoke EnableMenuItem,hMenu,IDM_SAVE,MF_ENABLED
invoke SendMessage,hToolBar,TB_ENABLEBUTTON,IDM_SAVE,TRUE
.else
invoke EnableMenuItem,hMenu,IDM_SAVE,MF_GRAYED
invoke SendMessage,hToolBar,TB_ENABLEBUTTON,IDM_SAVE,FALSE
.endif
ret
DisplayFacet endp
;
; ---------------------------------------------
; 加载状态栏 LoadStatusBar
; ---------------------------------------------
LoadStatusBar proc hWin
; 创建状态栏子窗口
invoke CreateStatusWindow,WS_CHILD OR WS_VISIBLE OR SBS_SIZEGRIP,
NULL,hWin,1
mov hWinStatus,eax
; 将状态栏分成四部分
invoke SendMessage,hWinStatus,SB_SETPARTS,4,offset dwStatusWidth
ret
LoadStatusBar endp
; ---------------------------------------------
; 显示状态栏信息 DisplayStatusBarInfo
; ---------------------------------------------
DisplayStatusBarInfo Proc
local CurLineNo ; 光标所在的行号
local stRange:CHARRANGE ; 选择区域的位置,用于获取光标所在的位置
local szBuffer[256]:byte ; 显示在状态栏某区域的信息缓冲区
; 获取光标所在位置(stRange.cpMin光标所在字符与控件中首字符的距离)
invoke SendMessage,hWinEdit,EM_EXGETSEL,0,addr stRange
; 获取光标所在的行号
invoke SendMessage,hWinEdit,EM_EXLINEFROMCHAR,0,-1
mov CurLineNo,eax
; 获取光标所在行(eax指示)的行首与控件中首字符的距离
invoke SendMessage,hWinEdit,EM_LINEINDEX,eax,0
mov ecx,stRange.cpMin
sub ecx,eax
inc ecx ;列号
inc CurLineNo ;行号
invoke wsprintf,addr szBuffer,addr szStatusFormat,CurLineNo,ecx
; 在状态栏显示行号、列号信息
invoke SendMessage,hWinStatus,SB_SETTEXT,3,addr szBuffer
ret
DisplayStatusBarInfo endp
; ---------------------------------------------
; 查找并标记出文字
; ---------------------------------------------
SearchString proc
local stFindText:FINDTEXTEX
; 设置查找范围
invoke SendMessage,hWinEdit,EM_EXGETSEL,0,addr stFindText.chrg
.if stFind.Flags & FR_DOWN
push stFindText.chrg.cpMax
pop stFindText.chrg.cpMin
.endif
mov stFindText.chrg.cpMax,-1
; 设置查找选项
mov stFindText.lpstrText,offset szFindText
mov ecx,stFind.Flags
and ecx,FR_MATCHCASE or FR_DOWN or FR_WHOLEWORD
; 查找并把光标设置到找到的文本上
invoke SendMessage,hWinEdit,EM_FINDTEXTEX,ecx,addr stFindText
.if eax == -1 ; 未查找到
invoke MessageBox,hWinMain, addr szNotFound, addr szFindCaption,MB_OK
ret
.endif
; 标记查找到的串
invoke SendMessage,hWinEdit,EM_EXSETSEL,0,addr stFindText.chrgText
invoke SendMessage,hWinEdit,EM_SCROLLCARET,NULL,NULL
ret
SearchString endp
; ---------------------------------------------
; 退出程序
; ---------------------------------------------
Quit proc
invoke Confirmation
.if hFile
invoke CloseHandle,hFile
.endif
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
ret
Quit endp
; -----------------------------------------------------
end start
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -