2024年4月10日发(作者:)

华 北 科 技 学 院

课程设计说明书

课程名称: 汇编语言

班级: 计算机B08-1 姓名:_李鹏飞_ __

学号:__ 2 __

设计题目:

___ win32编写记事本 ___

设计时间:

_ 6月23日 _

_ 7月1日 __

指导教师:_____ 杜杏菁_ ________________

评 语:_________________________________

_________________________________________

_________________________________________

_________________________________________

_________________________________________

评阅成绩:

__ __

评阅教师:

_____

一、课程设计目的

进行程序设计方法和技能的基本训练,巩固在课堂上学到的有关程序设计

的基本知识和基本方法,通过实际动手能力的培养,进一步熟悉汇编语言的结构

和使用方法,达到能独立阅读、编制和调试一定规模的汇编语言程序的水平。

二、课程设计要求

1.要求编写并调试通过一个小型软件,实现对软件或硬件的操作。

2.遵循模块化、结构化的程序设计方法。

3.要求程序必须正确。

4.程序简明易懂,多运用输入输出提示,出错信息及必要的注释。

5.要求程序结构合理,语句使用得当。

6.适当追求编程技巧和程序运行效率。

三、课程设计题目:

win32编写记事本

四、课题分析

WINDOW 记事本的编写,要求能实现基本菜单框架并打开窗口,有能力的同

学可以编写进行数据录入并保存的代码

五、流程图:

开 始

加载头文件

加载数据段

编译代码

设计窗体

编译生成文件

结 束

- 1 -

六、程序源代码:

.386

.model flat,stdcall

option casemap:none

include

include

includelib

include

includelib

include

includelib

include

includelib

include

includelib

ICO_MAIN EQU 1000h ;图标

IDM_MAIN EQU 2000h ;菜单

IDA_MAIN EQU 2000h ;加速键

IDM_NEW EQU 2101h ;新建

IDM_OPEN EQU 2102h ;打开

IDM_SAVE EQU 2103h ;保存

IDM_SAVEAS EQU 2104h ;另存为

IDM_EXIT EQU 2105h ;退出

IDM_UNDO EQU 2201h ;撤销

IDM_CUT EQU 2203h ;剪切

IDM_COPY EQU 2204h ;复制

IDM_PASTE EQU 2205h ;粘贴

IDM_DELETE EQU 2206h ;删除

IDM_FIND EQU 2207h ;查找

IDM_REPLACE EQU 220Ah ;替换

IDM_SELECTALL EQU 220Bh ;全选

IDM_FONT EQU 2301h ;字体

IDM_STATUSBAR EQU 2401h ;状态栏

IDM_HELP EQU 2501h ;帮助主题

IDM_ABOUT EQU 2502h ;关于

IDM_MENUHELP EQU 2601h ;菜单信息

.data?

hInstance dd ?

- 2 -

hWinMain dd ?

hMenu dd ?

hWinStatus dd ?

hWinEdit dd ?

hFile dd ?

hFindDialog dd ?

hRichEdit dd ?

dwFontColor dd ?

idFindMessage dd ?

stFind FINDREPLACE

szFindText db 100 dup (?)

szReplaceText db 100 dup (?)

szFileName db MAX_PATH dup (?)

stLogFont LOGFONT

dwOption dd ?

.data

F_STATUSBAR equ 00000001h

dllEdit db "",0

errTitle db "错误",0

noRichEdit db "无法找到"

className db "TextEditor",0

captionMain db "文本编辑器",0

classEdit db "RichEdit20A",0

fontFace db "Fixedsys",0

modify db "你已经改动过啦,要不要存一下?",0

filter db "文本文件(*.txt)",0,"*.txt",0,"所有文件

",0,"*.*",0,0

defExt db "txt",0

titleFormat db "%s - 我的记事本",0

errCreateFile db "咦!出现问题了!",0

errOpenFile db "咦!怎么打不开!",0

notFound db "不给力啊,找不到!",0

noName db "还没起名字",0

timeFormat db "%02d:%02d:%02d",0

charsFormat db "字节数:%d",0

lineFormat db "行:%d",0

colFormat db "列:%d",0

helpTitle db "帮助",0

helpText db "Sorry!无法提供任何帮助",0

aboutTitle db "关于 记事本",0

aboutText db "我的记事本",0ah,0dh,"作者:李鹏飞",0ah,0dh,"2010年

07月01日",0ah,0dh,0

dwStatusWidth dd 100,200,300,400,-1

- 3 -

dwMenuHelp dd 0,IDM_MENUHELP,0,0

FINDMSGSTRING db "commdlg_FindReplace",0

.code

;====================================================================

================================

_CheckModifyState PROC

invoke SendMessage,hWinEdit,EM_GETMODIFY,0,0

;获取控件内容是否改变的信息

.if eax != 0

invoke MessageBox,hWinMain,addr modify,addr captionMain,

MB_YESNOCANCEL or MB_ICONQUESTION

.if eax == IDYES

call _SaveFile

;有待改动

.elseif eax == IDCANCEL

mov eax,FALSE

ret

.endif

.endif

mov eax,TRUE

ret

_CheckModifyState ENDP

;====================================================================

================================

;Richedit的流出操作

_StreamProcOut PROC uses ebx edi esi _dwCookie,lpBuffer,NumBytes,pBytes

invoke WriteFile,hFile,lpBuffer,NumBytes,pBytes,0

xor eax,1

;如果ReadFile或WriteFile返回1(成功),则最终eax返回0,说明操作成功

ret

_StreamProcOut ENDP

;====================================================================

================================

;Richedit的流入操作

_StreamProcIn PROC uses ebx edi esi _dwCookie,lpBuffer,NumBytes,pBytes

invoke ReadFile,hFile,lpBuffer,NumBytes,pBytes,0

xor eax,1

;如果ReadFile或WriteFile返回1(成功),则最终eax返回0,说明操作成功

ret

- 4 -

_StreamProcIn ENDP

;====================================================================

================================

;设置字体和字体的颜色

_SetFont PROC _lpszFont,_dwFontSize,_dwColor

local @stCf:CHARFORMAT

invoke RtlZeroMemory,addr @stCf,sizeof @stCf

;开始填充stCf结构

mov @,sizeof @stCf

mov @,CFM_SIZE or CFM_FACE or CFM_BOLD or CFM_COLOR

;字段掩码,用来指定结构中哪些字段是有效的

push _dwFontSize

pop @t

push _dwColor

pop @Color

mov @cts,0

invoke lstrcpy,addr @Name,_lpszFont

invoke SendMessage,hWinEdit,EM_SETTEXTMODE,1,0

;设置工作模式

invoke SendMessage,hWinEdit,EM_SETCHARFORMAT,SCF_ALL,addr

@stCf ;为控件中的全部文本设置指定的格式

ret

_SetFont ENDP

;====================================================================

================================

;查找文字

_FindText PROC

local @stFindText:FINDTEXTEX

;设置查找区域

invoke SendMessage,hWinEdit,EM_EXGETSEL,0,addr

@

.if & FR_DOWN

;向下查找

push @

pop @

;将这个选择区域的结束位置用做下一次查找的起始点

.endif

mov @,-1

;一直查找到全部文本的最后

;设置查找选项

- 5 -

mov @ext,offset szFindText

mov ecx,

and ecx,FR_MATCHCASE or FR_DOWN or FR_WHOLEWORD

;查找并把光标设置到找到的文本上

invoke SendMessage,hWinEdit,EM_FINDTEXTEX,ecx,addr @stFindText

;ecx中存储的是搜索选项

.if eax == -1

mov ecx,hWinMain

.if hFindDialog

mov ecx,hFindDialog

.endif

invoke MessageBox,ecx,addr notFound,NULL,MB_OK or

MB_ICONINFORMATION

ret

.endif

;找到文本以后,文本的位置在FINDTEXTEX结构的chrgText字段中返

回,chrgText字段是一个CHARRANGE结构,直接在EM_EXSETSEL消息中使用它将选

择区域设置到找到的文字上

invoke SendMessage,hWinEdit,EM_EXSETSEL,0,addr

@xt

invoke SendMessage,hWinEdit,EM_SCROLLCARET,NULL,NULL

;卷动文字,以便找到的文本能够出现在用户的视野中

ret

_FindText ENDP

;====================================================================

================================

;保存文件,如果没有打开或创建文件则另存为

_SaveFile PROC

local @stES:EDITSTREAM

.if ! hFile

call _SaveAs

.if ! eax

ret

.endif

.endif

mov @ie,FALSE

;在Richedit的流操作中写文件

mov @r,NULL

mov @lback,offset _StreamProcOut

;回调函数

invoke SendMessage,hWinEdit,EM_STREAMOUT,SF_TEXT,addr @stES

- 6 -

;流出操作,文本格式是简单的文本格式

invoke SendMessage,hWinEdit,EM_SETMODIFY,FALSE,0

;设置修改状态

mov eax,TRUE

ret

_SaveFile ENDP

;====================================================================

=================================

;另存为

_SaveAs PROC

local @stOF:OPENFILENAME

local @stEs:EDITSTREAM

invoke RtlZeroMemory,addr @stOF,sizeof @stOF

;显示"保存文件"对话框

;填充stOF结构

mov @tSize,sizeof @stOF

push hWinMain

pop @ner

;所属窗口

mov @ilter,offset filter

;指定文件名筛选字符串

mov @ile,offset szFileName

mov @le,MAX_PATH

;指定lpstrFile参数指向的缓冲区的长度,260

mov @,OFN_PATHMUSTEXIST

;路径必须存在

mov @efExt,offset defExt

;默认扩展名

mov @itle,NULL

;标题为“另存为”

invoke GetSaveFileName,addr @stOF

.if eax

;创建新文件

invoke CreateFile,addr szFileName,GENERIC_READ or

GENERIC_WRITE, ;存取方式:为读写

FILE_SHARE_READ,

;共享属性:允许其他进程同时以读方式打开文件

0,

;安全属性:无法被继承

CREATE_ALWAYS,

- 7 -

;创建新文件,如果文件已经存在则清除原文件

FILE_ATTRIBUTE_NORMAL,

;文件属性:普通文件

0

;文件模板句柄

.if eax != INVALID_HANDLE_VALUE

push eax

.if hFile

;有打开的文件

invoke CloseHandle,hFile

.endif

pop eax

;保存文件

mov hFile,eax

;文件句柄

call _SaveFile

call _SetCaption

call _SetStatus

mov eax,TRUE

ret

.else

invoke MessageBox,hWinMain,addr

errCreateFile,NULL,MB_OK or MB_ICONERROR

.endif

.endif

mov eax,FALSE

ret

_SaveAs ENDP

;====================================================================

=================================

;打开及输入文件

_OpenFile PROC

local @stOF:OPENFILENAME

local @stES:EDITSTREAM

invoke RtlZeroMemory,addr @stOF,sizeof @stOF

;显示“打开文件”对话框

mov @tSize,sizeof @stOF

push hWinMain

pop @ner

mov @ilter,offset filter

mov @ile,offset szFileName

mov @le,MAX_PATH

mov @,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST

- 8 -

;文件必须存在

invoke GetOpenFileName,addr @stOF

.if eax

;创建文件

invoke CreateFile,addr szFileName,GENERIC_READ or

GENERIC_WRITE,

FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0

;打开存在的文件,当文件不存在时函数会返回失败

.if eax == INVALID_HANDLE_VALUE

invoke MessageBox,hWinMain,addr errOpenFile,NULL,MB_OK

or MB_ICONSTOP

ret

.endif

push eax

.if hFile

invoke CloseHandle,hFile

.endif

pop eax

mov hFile,eax

;读入文件

mov @ie,TRUE

;在Richedit的流操作中读文件

mov @r,NULL

mov @lback,offset _StreamProcIn

invoke SendMessage,hWinEdit,EM_STREAMIN,SF_TEXT,addr @stES

;流入操作,文本格式是简单的文本格式

invoke SendMessage,hWinEdit,EM_SETMODIFY,FALSE,0

;设置修改状态

call _SetCaption

call _SetStatus

.endif

ret

_OpenFile ENDP

;====================================================================

=================================

;选择字体

_ChooseFont PROC

local @stCF:CHOOSEFONT

invoke RtlZeroMemory,addr @stCF,sizeof @stCF

mov @tSize,sizeof @stCF

push hWinMain

pop @ner

- 9 -

mov @ont,offset stLogFont

;指定字体的名称和属性

push dwFontColor

pop @ors

mov @,CF_SCREENFONTS or CF_INITTOLOGFONTSTRUCT or

CF_EFFECTS ;字体列表中只显示屏幕字体,对话框中显示“效果”复选框

invoke ChooseFont,addr @stCF

.if eax

push @ors

pop dwFontColor

mov eax,@Size

;用户选择的字体大小,单位是1/10磅

shl eax,1

invoke _SetFont,addr

Name,eax,@ors

.endif

ret

_ChooseFont ENDP

;====================================================================

=================================

;设置标题栏的显示内容

_SetCaption PROC

local @szBuffer[1024]:byte

.if szFileName

;如果当前是某一文件,则显示文件名

mov eax,offset szFileName

.else

mov eax,offset noName

;否则显示未命名

.endif

invoke wsprintf,addr @szBuffer,addr titleFormat,eax

invoke SetWindowText,hWinMain,addr @szBuffer

ret

_SetCaption ENDP

;====================================================================

=================================

;设置菜单项,状态栏的状态和信息

_SetStatus PROC

local @stRange:CHARRANGE

local @dwLines,@dwLine,@dwLineStart

local @szBuffer[256]:byte

- 10 -

local @stST:SYSTEMTIME

;在状态栏显示行列信息

invoke GetWindowTextLength,hWinEdit

invoke wsprintf,addr @szBuffer,addr charsFormat,eax

invoke SendMessage,hWinStatus,SB_SETTEXT,2,addr @szBuffer

;总字节数

invoke SendMessage,hWinEdit,EM_EXGETSEL,0,addr @stRange

;获取选定区域

invoke SendMessage,hWinEdit,EM_EXLINEFROMCHAR,0,-1

;得知指定的字符位于哪一行中

mov @dwLine,eax

invoke SendMessage,hWinEdit,EM_LINEINDEX,eax,0

;获取指定行的起始字符的位置

mov ecx,@

sub ecx,eax

inc ecx

;显示给用户的列号从1开始编号

invoke wsprintf,addr @szBuffer,addr colFormat,ecx

invoke SendMessage,hWinStatus,SB_SETTEXT,1,addr @szBuffer

;光标所在位置的列

inc @dwLine

;显示给用户的行号从1开始

invoke wsprintf,addr @szBuffer,addr lineFormat,@dwLine

invoke SendMessage,hWinStatus,SB_SETTEXT,0,addr @szBuffer

;光标所在位置的行

;根据情况改变菜单项的状态

mov eax,@

.if eax == @

;选中区域为空则复制粘贴删除不可用

invoke EnableMenuItem,hMenu,IDM_COPY,MF_GRAYED

invoke EnableMenuItem,hMenu,IDM_CUT,MF_GRAYED

.else

invoke EnableMenuItem,hMenu,IDM_COPY,MF_ENABLED

invoke EnableMenuItem,hMenu,IDM_CUT,MF_ENABLED

.endif

invoke IsClipboardFormatAvailable,CF_TEXT

;判断剪贴板的格式是否是文本格式

.if eax

;如果剪贴板有内容则可以粘贴

- 11 -

invoke EnableMenuItem,hMenu,IDM_PASTE,MF_ENABLED

.else

invoke EnableMenuItem,hMenu,IDM_PASTE,MF_GRAYED

.endif

invoke GetWindowTextLength,hWinEdit

.if eax

;如果可以全选

invoke EnableMenuItem,hMenu,IDM_SELECTALL,MF_ENABLED

.else

invoke EnableMenuItem,hMenu,IDM_SELECTALL,MF_GRAYED

.endif

invoke SendMessage,hWinEdit,EM_GETMODIFY,0,0

.if eax

;如果可以保存

invoke EnableMenuItem,hMenu,IDM_SAVE,MF_ENABLED

.else

invoke EnableMenuItem,hMenu,IDM_SAVE,MF_GRAYED

.endif

.if dwOption & F_STATUSBAR

;如果选中了状态栏

invoke CheckMenuItem,hMenu,IDM_STATUSBAR,MF_CHECKED

.else

invoke CheckMenuItem,hMenu,IDM_STATUSBAR,MF_UNCHECKED

.endif

ret

_SetStatus ENDP

;====================================================================

=================================

_Resize PROC

local @stRect:RECT

local @stRectTemp:RECT

local @dwWidth,@dwHeight

;取得窗口客户区的大小

invoke GetClientRect,hWinMain,addr @stRect

mov eax,@

sub eax,@

mov @dwWidth,eax

- 12 -

mov eax,@

sub eax,@

mov @dwHeight,eax

;计算及调整状态栏

.if dwOption & F_STATUSBAR

invoke ShowWindow,hWinStatus,SW_SHOW

invoke MoveWindow,hWinStatus,0,0,0,0,TRUE

invoke GetWindowRect,hWinStatus,addr @stRectTemp

mov eax,@

sub eax,@

sub @dwHeight,eax

.else

invoke ShowWindow,hWinStatus,SW_HIDE

.endif

;调整Richedit控件位置

invoke

MoveWindow,hWinEdit,@,@,@dwWidth,@dwHeight,T

RUE

ret

_Resize ENDP

;====================================================================

=================================

_Quit PROC

invoke _CheckModifyState

.if eax

invoke DestroyWindow,hWinMain

invoke PostQuitMessage,NULL

;产生一条 WM_QUIT 消息

.if hFile

;如果有打开的文件则关闭

invoke CloseHandle,hFile

.endif

.endif

invoke KillTimer,hWinMain,1

;取消定时器

ret

_Quit ENDP

;====================================================================

=================================

_CreateWindow PROC

- 13 -

; 注册“查找”对话框消息,初始化“查找”对话框的结构

mov tSize,sizeof stFind

;结构的长度

push hWinMain

pop ner

;指定所属窗口

mov ,FR_DOWN

;把“方向”单选钮设置为“向下”

mov indWhat,offset szFindText

;lpstrFindWhat指向包含查找字符串的指针

mov hatLen,sizeof szFindText

;wFindWhatLen指示lpstrFindWhat缓存区的长度

mov eplaceWith,offset szReplaceText

;指向包含替换为字符串的指针

mov ceWithLen,sizeof szReplaceText

;lpstrReplaceWith缓存区的长度

invoke RegisterWindowMessage,addr FINDMSGSTRING

;注册自定义的消息

mov idFindMessage,eax

;eax中返回消息ID

;建立状态栏

invoke CreateStatusWindow,SBARS_SIZEGRIP or WS_CHILD or

WS_VISIBLE, ;显示状态栏右下角的斜条

NULL,hWinMain,2

;父窗口为hWinMain,状态栏控件的ID为2,初始化字符串为NULL

mov hWinStatus,eax

invoke SendMessage,hWinStatus,SB_SETPARTS,5,offset

dwStatusWidth ;分成四栏

;建立输出文本窗口

invoke CreateWindowEx,WS_EX_CLIENTEDGE,offset classEdit,NULL,

;客户区立体边框

WS_CHILD OR WS_VISIBLE OR WS_VSCROLL OR WS_HSCROLL

OR ES_MULTILINE or ES_NOHIDESEL,

;可以编辑多行文字,失去键盘输入焦点的时候仍然显示选择区域

0,0,0,0,

hWinMain,0,hInstance,NULL

;0指定的是子窗口的ID号

mov hWinEdit,eax

or dwOption,F_STATUSBAR

;注释

invoke _SetCaption

;设置标题

- 14 -

invoke _SetStatus

;设置状态栏

invoke _SetFont,addr fontFace,9 * 20,0

;注释

;在使用多行Edit控件时,父窗口发送 EM_SETEVENTMASK 消息给

RichEdit 控件,指定它对哪些消息感兴趣

;wParam必须为0,ENM_CHANGE 发送 EN_CHANGE 通知NM_SELCHANGE 发

送 EN_SELCHANGE 通知

invoke SendMessage,hWinEdit,EM_SETEVENTMASK,0,ENM_CHANGE or

ENM_SELCHANGE or ENM_MOUSEEVENTS

invoke SendMessage,hWinEdit,EM_EXLIMITTEXT,0,-1

;设置控件中能够容纳字符的总数,0FFFFFFFFh(-1) 字节

invoke SendMessage,hWinMain,EM_EMPTYUNDOBUFFER,0,0

;清空undo,redo队列

ret

_CreateWindow ENDP

;====================================================================

================================

;窗口过程

_ProcWinMain PROC uses ebx edi esi hWnd,uMsg,wParam,lParam

local @stRange:CHARRANGE

local @stST:SYSTEMTIME

local @szBuffer[128]:byte

local @pt:POINT

local hPopup:DWORD

local @stES:EDITSTREAM

mov eax,uMsg

.if eax == WM_CREATE

push hWnd

pop hWinMain

invoke _CreateWindow

invoke SetTimer,hWinMain,1,300,NULL

;设置定时器

.elseif eax == WM_DROPFILES

;拖放文件

call _CheckModifyState

.if eax == FALSE

call _SaveFile

.endif

invoke DragQueryFile,wParam,0,addr szFileName,128

;获取文件的路径

invoke CreateFile,addr szFileName,GENERIC_READ or

- 15 -

GENERIC_WRITE,

FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 ;打开

文件

mov hFile,eax

mov @ie,TRUE

;在Richedit的流操作中读文件

mov @r,NULL

mov @lback,offset _StreamProcIn

invoke SendMessage,hWinEdit,EM_STREAMIN,SF_TEXT,addr @stES

;流入操作,文本格式是简单的文本格式

invoke SendMessage,hWinEdit,EM_SETMODIFY,FALSE,0

;设置修改状态

call _SetCaption

call _SetStatus

.elseif eax == WM_TIMER

invoke GetLocalTime,addr @stST

movzx eax,@

movzx ebx,@e

movzx ecx,@d

invoke wsprintf,addr @szBuffer,addr timeFormat,eax,ebx,ecx

invoke SendMessage,hWinStatus,SB_SETTEXT,3,addr @szBuffer

.elseif eax == WM_SIZE

invoke _Resize

.elseif eax == WM_NOTIFY

mov eax,lParam

mov eax,[eax + om]

.if eax == hWinEdit

invoke _SetStatus

.endif

push esi

mov esi,lParam

assume esi:ptr NMHDR

.if [esi].code == EN_MSGFILTER

;鼠标滑轮发送的消息

assume esi:ptr MSGFILTER

.if [esi].msg == WM_RBUTTONDOWN

invoke GetMenu,hWinMain

;获取窗口主菜单句柄

invoke GetSubMenu,eax,1

;获取弹出式子菜单的句柄

mov hPopup,eax

invoke _SetStatus

mov edx,[esi].lParam

- 16 -

;位置信息

mov ecx,edx

and edx,0FFFFh

shr ecx,16

mov @pt.x,edx

mov @pt.y,ecx

invoke ClientToScreen,hWinMain,addr @pt

invoke TrackPopupMenu,hPopup,TPM_LEFTALIGN or

TPM_BOTTOMALIGN,@pt.x,@pt.y,NULL,hWinMain,NULL

.endif

.endif

pop esi

.elseif eax == WM_MENUSELECT

invoke

MenuHelp,WM_MENUSELECT,wParam,lParam,lParam,hInstance,hWinStatus,

offset dwMenuHelp

.elseif eax == WM_COMMAND

mov eax,wParam

movzx eax,ax

.if eax == IDM_OPEN

invoke _CheckModifyState

.if eax

;eax == TRUE 说明没有被修改

call _OpenFile

.endif

.elseif eax == IDM_NEW

invoke _CheckModifyState

.if eax

.if hFile

invoke CloseHandle,hFile

mov hFile,0

.endif

mov szFileName,0

invoke SetWindowText,hWinEdit,NULL

invoke _SetCaption

invoke _SetStatus

.endif

.elseif eax == IDM_SAVE

call _SaveFile

.elseif eax == IDM_SAVEAS

call _SaveAs

.elseif eax == IDM_EXIT

call _Quit

.elseif eax == IDM_UNDO

- 17 -

invoke SendMessage,hWinEdit,EM_UNDO,0,0

.elseif eax == IDM_SELECTALL

mov @,0

mov @,-1

invoke SendMessage,hWinEdit,EM_EXSETSEL,0,addr @stRange

.elseif eax == IDM_COPY

invoke SendMessage,hWinEdit,WM_COPY,0,0

.elseif eax == IDM_CUT

invoke SendMessage,hWinEdit,WM_CUT,0,0

.elseif eax == IDM_PASTE

invoke SendMessage,hWinEdit,WM_PASTE,0,0

.elseif eax == IDM_FIND

and ,not FR_DIALOGTERM

;FR_DIALOGTERM代表取消按钮

invoke FindText,addr stFind

.if eax

mov hFindDialog,eax

.endif

.elseif eax == IDM_FONT

invoke _ChooseFont

.elseif eax == IDM_STATUSBAR

xor dwOption,F_STATUSBAR

;注释

invoke _Resize

.elseif eax == IDM_HELP

invoke MessageBox,NULL,offset helpText,offset

helpTitle,MB_OK or MB_ICONQUESTION

.elseif eax == IDM_ABOUT

invoke MessageBox,NULL,offset aboutText,offset

aboutTitle,MB_OK

.endif

.elseif eax == idFindMessage

.if & FR_DIALOGTERM

mov hFindDialog,0

.else

invoke _FindText

.endif

.elseif eax == WM_ACTIVATE

;窗口激活

mov eax,wParam

.if (ax == WA_CLICKACTIVE ) || (ax == WA_ACTIVE)

;由鼠标点击激活或被鼠标点击以外的方法激活

invoke SetFocus,hWinEdit

.endif

- 18 -

.elseif eax == WM_CLOSE

call _Quit

.else

invoke DefWindowProc,hWnd,uMsg,wParam,lParam

ret

.endif

xor eax,eax

ret

_ProcWinMain ENDP

;====================================================================

================================

_WinMain PROC

local @stWndClass:WNDCLASSEX

local @stMsg:MSG

local @hAccelerator

invoke GetModuleHandle,NULL ;得到

应用程序的句柄

mov hInstance,eax

invoke LoadMenu,hInstance,IDM_MAIN ;加载

菜单,IDM_MAIN指定要装入的菜单资源ID

mov hMenu,eax ;eax返回

菜单句柄

invoke LoadAccelerators,hInstance,IDA_MAIN ;

加载加速键

mov @hAccelerator,eax

;注册窗口类

;注册窗口之前,先填充传递给RegisterClassEx函数的结构体参数, 指

定窗口的属性

invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass

;把stWndClass变量初始化为0

invoke LoadIcon,hInstance,ICO_MAIN

mov @,eax ;指定

显示在窗口标题栏左上角的图标

mov @m,eax

invoke LoadCursor,0,IDC_ARROW ;

指定了鼠标在窗口中的光标形状

mov @r,eax

push hInstance

pop @nce ;指定

要注册的窗口类属于哪个模块

- 19 -

mov @,sizeof WNDCLASSEX ;指定

WNDCLASSEX结构的长度

mov @,CS_HREDRAW or CS_VREDRAW ;

窗口的宽度或高度改变时重画窗口

mov @dProc,offset _ProcWinMain ;

窗口过程的偏移

mov @kground,COLOR_BTNFACE + 1 ;

窗口客户区的背景色

mov @assName,offset className ;

指定程序要建立的类命名

;注册窗口

invoke RegisterClassEx,addr @stWndClass

;建立并显示窗口

invoke CreateWindowEx,WS_EX_ACCEPTFILES,

;dwExstyle,允许窗口进行拖放操作

offset className,offset captionMain,

WS_OVERLAPPEDWINDOW,

;WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_THICKFRAME or

WS_MINIMIZEBOX or WS_MAXIMIZEBOX

CW_USEDEFAULT,CW_USEDEFAULT,700,500, ;窗口

的位置和大小,CW_USEDEFAULT,Windows会自动为窗口指定最合适的位置

NULL,hMenu,hInstance,NULL ;窗口

所属的父窗口为空

mov hWinMain,eax ;eax中返

回窗口句柄

invoke ShowWindow,hWinMain,SW_SHOWNORMAL ;显示

窗口,显示方式为:显示并激活窗口,恢复正常大小

invoke UpdateWindow,hWinMain ;绘制

客户区

;消息循环

.while TRUE

invoke GetMessage,addr @stMsg,NULL,0,0 ;

获取消息队列中的消息,NULL表示获取的是所有本程序所属窗口的消息,两个0

表示获取所有编号的消息

.break .if eax == 0 ;说明

获取的消息是WM_QUIT

invoke TranslateAccelerator,hWinMain,@hAccelerator,addr

@stMsg

.if eax == 0

invoke TranslateMessage,addr @stMsg ;将MSG

结构传给Windows进行一些键盘消息的转换

invoke DispatchMessage,addr @stMsg ;将消

- 20 -

息发送的窗口过程去处理

.endif

.endw

ret

_WinMain ENDP

;====================================================================

================================

main:

invoke LoadLibrary,offset dllEdit ;装入

Richedit库文件

.if eax != 0

mov hRichEdit,eax ;函数返回

装入dll的模块实例句柄

call _WinMain

invoke FreeLibrary,hRichEdit ;不再

使用库文件,将库释放

.else

invoke MessageBox,NULL,addr noRichEdit,addr errTitle,MB_OK

or MB_ICONERROR

.endif

invoke ExitProcess,NULL

END main

七、结果显示

- 21 -

八、感想、收获及体会

- 22 -