📄 richedit.asm
字号:
; 版本5,用RichEdit流式操作实现文件的打开与保存
; 响应 UNDO、REDO、CUT、PASTE、DEL菜单项
; 版本4,增加文件打开、文件保存、文件另存为、退出菜单的响应
; 版本3,增加了菜单显示
; 版本2,增加了图标显示
; 版本1,增加了RichEdit控件,可以进行文本编辑
; 版本0,仅显示一个窗口
.386
.model flat,stdcall
option casemap:none
;----------------------------------------------
; Include 文件定义
;----------------------------------------------
include richedit.inc ; 自定义的头文件,包含函数说明
include windows.inc
include gdi32.inc
includelib gdi32.lib
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include comdlg32.inc
includelib comdlg32.lib
include comctl32.inc ; 工具栏等通用控件
includelib comctl32.lib
;----------------------------------------------
; 数据段
;----------------------------------------------
.data
hInstance dd ?
hWinMain dd ?
CommandLine dd ?
szFileName db MAX_PATH dup (?) ; 文件名缓冲区(包括路径在内)
; MAX_PATH 在 Windows.inc中定义
hWinEdit dd ? ; RichEdit控件句柄
hFile dd 0 ; 文件句柄
hAccelerator dd ?
hMenu dd ? ; 菜单句柄
hToolBar dd ? ; 工具栏句柄
hTbBmp dd ? ; 工具栏上的位图句柄
hWinStatus dd ? ; 状态栏句柄
hFindDialog dd 0 ; 查找与替换对话框的句柄
stFind FINDREPLACE <?> ; 查找与替换结构变量
szFindText db 100 dup(0) ; 查找字符串的缓冲区
idFindMessage dd 0 ; 查找和替换对话框的消息
.const
szClassName db 'Rich_Edit_Class',0
szCaptionMain db 'Richedit',0
szClassEdit db 'RichEdit20A',0
szDllEdit db 'RichEd20.dll',0
szFilter db 'Text Files(*.txt)',0,'*.txt',0
db 'All Files(*.*)',0,'*.*',0,0
szDefaultExt db 'txt',0
szErrOpenFile db '无法打开文件!',0
szClassTool db 'ToolbarWindow32',0 ; 工具栏的类名
szDisplayName db "MASM32 Richedit",0
dwStatusWidth dd 50,150,300,-1 ; 状态栏的分隔点的坐标
szStatusFormat db ' 行 %d 列 %d',0
szFindMessage db 'commdlg_FindReplace',0
szFindCaption db '查找字符串',0
szNotFound db '字符串搜索完毕',0
TBSE equ TBSTATE_ENABLED
TBSB equ TBSTYLE_BUTTON
lpButtons equ this byte
TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
TBBUTTON <STD_FILENEW,IDM_NEW,TBSE,TBSB,0,0,-1>
TBBUTTON <STD_FILEOPEN,IDM_OPEN,TBSE,TBSB,0,0,-1>
TBBUTTON <STD_FILESAVE,IDM_SAVE,TBSE,TBSB,0,0,-1>
TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
TBBUTTON <STD_CUT,IDM_CUT,TBSE,TBSB,0,0,-1>
TBBUTTON <STD_COPY,IDM_COPY,TBSE,TBSB,0,0,-1>
TBBUTTON <STD_PASTE,IDM_PASTE,TBSE,TBSB,0,0,-1>
TBBUTTON <STD_UNDO,IDM_UNDO,TBSE,TBSB,0,0,-1>
TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
TBBUTTON <STD_FIND,IDM_FIND,TBSE,TBSB,0,0,-1>
TBBUTTON <STD_REPLACE,IDM_FINDNEXT,TBSE,TBSB,0,0,-1>
TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
TBBUTTON <STD_DELETE,IDM_DEL,TBSE,TBSB,0,0,-1>
;TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
;TBBUTTON <0,IDM_NEW,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
;TBBUTTON <1,IDM_OPEN,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
;TBBUTTON <2,IDM_SAVE,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
;TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
;TBBUTTON <3,IDM_CUT,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
;TBBUTTON <4,IDM_COPY,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
;TBBUTTON <5,IDM_PASTE,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
;TBBUTTON <6,IDM_UNDO,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
;TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
;TBBUTTON <7,IDM_FIND,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
;TBBUTTON <8,IDM_FINDNEXT,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
;TBBUTTON <0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1>
;TBBUTTON <9,IDM_DEL,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1>
;----------------------------------------------
; 代码段
;----------------------------------------------
.code
;----------------------------------------------
; 主程序
;----------------------------------------------
start:
invoke GetModuleHandle, NULL ; 获得实例句柄
mov hInstance, eax
invoke GetCommandLine ; 获得命令行地址
mov CommandLine, eax
invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT
; 进入窗口主程序函数
invoke ExitProcess,eax ; 退出并返回操作系统
;----------------------------------------------
; 窗口主程序
;----------------------------------------------
WinMain proc hInst :DWORD,
hPrevInst :DWORD,
CmdLine :DWORD,
CmdShow :DWORD
LOCAL Wwd :DWORD ; 窗口的宽度
LOCAL Wht :DWORD ; 窗口的高度
LOCAL Wtx :DWORD ; 窗口的左上角在屏幕上的水平坐标
LOCAL Wty :DWORD ; 窗口的左上角在屏幕上的纵坐标
LOCAL wc :WNDCLASSEX ; 窗口结构变量,存放创建窗口时需要的信息
LOCAL msg :MSG ; 消息结构变量,存放获取的消息
LOCAL hRichEdit:DWORD ; RichEdit库句柄
invoke LoadLibrary,offset szDllEdit ; 装入RichEdit20.dll库
mov hRichEdit,eax
invoke RtlZeroMemory,addr wc, sizeof wc ; 将结构变量wc中的各项清0
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, offset WndProc
push hInst
pop wc.hInstance
mov wc.lpszClassName, offset szClassName
mov wc.hbrBackground,COLOR_WINDOW + 1
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor, eax
invoke LoadIcon,hInst,MAIN_ICON ; 从资源节区装入图标
mov wc.hIcon,eax
invoke RegisterClassEx, ADDR wc ; 注册窗口
invoke LoadMenu,hInst,IDM_MAIN
mov hMenu,eax
; 计算主窗口的大小及显示位置
invoke WindowSizePosition, addr Wtx,addr Wty,addr Wwd, addr Wht
; 创建可显示窗口
invoke CreateWindowEx,WS_EX_CLIENTEDGE,
ADDR szClassName,
ADDR szCaptionMain,
WS_OVERLAPPEDWINDOW,
Wtx,Wty,Wwd,Wht,
NULL,hMenu,
hInst,NULL
mov hWinMain,eax ; 保存窗口句柄
invoke ShowWindow,hWinMain,SW_SHOWNORMAL ; 显示窗口
invoke UpdateWindow,hWinMain
invoke LoadAccelerators,hInstance,IDA_MAIN ;建立快捷键表
mov hAccelerator, eax
StartLoop: ; 消息循环
invoke GetMessage,ADDR msg,NULL,0,0 ; 获取消息
cmp eax, 0 ; 0,表示是退出消息
je ExitLoop
invoke TranslateAccelerator,hWinMain,hAccelerator,ADDR msg
invoke TranslateMessage, ADDR msg ; 转换消息
invoke DispatchMessage, ADDR msg ; 分发到窗口消息处理程序
jmp StartLoop
ExitLoop:
invoke FreeLibrary,hRichEdit ; 释放RichEdit库
mov eax, msg.wParam
ret
WinMain endp
; ---------------------------------------------
; 窗口消息处理程序
; ---------------------------------------------
WndProc proc uses ebx edx esi hWnd,uMsg,wParam,lParam
local stRange:CHARRANGE
local stPos:POINT
mov eax,uMsg
.if eax == WM_CLOSE
invoke Quit
.elseif eax == WM_CREATE
invoke Init , hWnd
.elseif eax == WM_SIZE
invoke AdjustLayout ; 调整工具栏、RichEdit控件、状态栏的显示位置和大小
.elseif eax == WM_NOTIFY
mov ebx, lParam
mov ecx, [ebx+NMHDR.hwndFrom]
.if [ebx+NMHDR.code] == TTN_NEEDTEXT ;显示工具的提示
assume ebx:ptr TOOLTIPTEXT
mov eax, [ebx].hdr.idFrom
mov [ebx].lpszText, eax
push hInstance
pop [ebx].hInst
assume ebx:nothing
.elseif ecx == hWinEdit
invoke DisplayStatusBarInfo
invoke DisplayFacet
.endif
.elseif eax == WM_COMMAND
mov eax,wParam
movzx eax,ax
.if eax == IDM_OPEN
invoke Confirmation
invoke OpenTextFile
.if hFile ; 显示打开的文件名
invoke SetWindowText,hWnd,offset szFileName
.endif
.elseif eax == IDM_NEW
invoke Confirmation
invoke SetWindowText,hWinEdit,NULL
invoke SetWindowText,hWnd,offset szCaptionMain
invoke DisplayFacet
.elseif eax == IDM_SAVE
invoke SaveFile
.elseif eax == IDM_SAVEAS
invoke SaveFileAs
.elseif eax == IDM_EXIT
invoke Quit
.elseif eax == IDM_UNDO
invoke SendMessage,hWinEdit,EM_UNDO,0,0
.elseif eax == IDM_CUT
invoke SendMessage,hWinEdit,WM_CUT,0,0
.elseif eax == IDM_COPY
invoke SendMessage,hWinEdit,WM_COPY,0,0
.elseif eax == IDM_PASTE
invoke SendMessage,hWinEdit,EM_PASTESPECIAL,CF_TEXT,0
.elseif eax == IDM_DEL
invoke SendMessage,hWinEdit,WM_CLEAR,0,0
.elseif eax == IDM_SELECT
mov stRange.cpMin,0
mov stRange.cpMax,-1
invoke SendMessage,hWinEdit,EM_EXSETSEL,0,addr stRange
.elseif eax == IDM_FIND
.if hFindDialog == 0
mov stFind.lStructSize,sizeof FINDREPLACE
push hWnd
pop stFind.hwndOwner
push hInstance
pop stFind.hInstance
mov stFind.Flags,FR_DOWN
mov stFind.lpstrFindWhat,offset szFindText
mov stFind.wFindWhatLen,sizeof szFindText
invoke FindText,offset stFind
mov hFindDialog,eax
.endif
.endif
.elseif eax == idFindMessage
.if stFind.Flags & FR_FINDNEXT
invoke SearchString
.elseif stFind.Flags & FR_DIALOGTERM
mov hFindDialog, 0
.endif
; 按下右键时弹出一个POPUP菜单
.elseif eax==WM_RBUTTONDOWN
invoke GetCursorPos,addr stPos
invoke TrackPopupMenu,hWinEdit,TPM_LEFTALIGN,stPos.x,stPos.y,NULL,hWnd,NULL
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
WndProc endp
; --------------------------------------------------------------
; 计算窗口大小和显示位置
; 窗口大小为屏幕的 3/4, 显示位置在中间,即屏幕宽、高的 1/8
; --------------------------------------------------------------
WindowSizePosition PROC lpx,lpy,lpwidth,lphight
LOCAL x,y,w,h
invoke GetSystemMetrics,SM_CXSCREEN ; 获取屏幕宽度
mov w, eax
mov x, eax
shr eax, 2
sub w, eax ; 主窗口宽度为屏幕原宽度的 3/4
shr x, 3 ; 左上角的x坐标
invoke GetSystemMetrics,SM_CYSCREEN ; 获取屏幕高度
mov h, eax
mov y, eax
shr eax, 2
sub h, eax ; 主窗口高度为屏幕原高度的 3/4
shr y, 3
push x
push y
push w
push h
mov ebx, lphight
pop dword ptr [ebx]
mov ebx, lpwidth
pop dword ptr [ebx]
mov ebx, lpy
pop dword ptr [ebx]
mov ebx, lpx
pop dword ptr [ebx]
ret
WindowSizePosition endp
; ---------------------------------------------
; 窗口初始化,WM_CREATE消息的处理程序
; ---------------------------------------------
Init Proc hWin
invoke LoadToolBar,hWin
invoke LoadStatusBar,hWin
; 注意:调整了RichEdit控件子窗的纵向显示位置,在前面留出了菜单栏大小
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -