win32汇编之——记事本程序

最近发现,虽然有一段时间没有写代码了,但是以前积累的经验对解决现在的一些问题,还是挺有益处的。以前一直打算深入理解下windows系统,但这个需要很多的时间和精力,所以没有尝试。最近打开书柜,发现很久以前买了《windows环境下32位汇编语言程序设计》第三版(后来好像还出第四版了),罗云彬写的。这本书其实以前也看过,但现在已经没什么印象了,打算拿来重新翻看一下,进一步掌握 windows编程的一些细节。

当然,要掌握 windows编程,本人又在网上买了一本《windows程序设计》第五版(珍藏版),这本书提供了windows编程的基础知识,很有用,虽然是1998年写的。

在此不打算细列windows的各个技术知识细节,因为实在是太多了,还是列一个实际的例子吧。一个win32开发的记事本程序。
 

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 4th Edition>
; by 罗云彬, luoyunbin@hotmail.com
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Richedit.asm
; “丰富编辑”控件的使用例子
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Richedit.asm
; rc Richedit.rc
; Link /subsystem:windows Richedit.obj Richedit.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		.386
		.model flat, stdcall
		option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include		windows.inc
include		user32.inc
includelib	user32.lib
include		kernel32.inc
includelib	kernel32.lib
include		comdlg32.inc
includelib	comdlg32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN	equ	1000
IDA_MAIN	equ	2000
IDM_MAIN	equ	2000
IDM_NEW		equ	2101
IDM_OPEN	equ	2102
IDM_SAVE	equ	2103
IDM_SAVEAS equ	2104
IDM_EXIT	equ	2105
IDM_UNDO	equ	2201
IDM_REDO	equ	2202
IDM_SELALL	equ	2203
IDM_COPY	equ	2204
IDM_CUT		equ	2205
IDM_PASTE	equ	2206
IDM_FIND	equ	2207
IDM_FINDPREV	equ	2208
IDM_FINDNEXT	equ	2209
IDM_Help  equ 3101
IDM_ABOUT  equ 3102
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		.data?
hInstance	dd	?
hWinMain	dd	?
hMenu		dd	?
hWinEdit	dd	?
hFile		dd	?
hFindDialog	dd	?
idFindMessage	dd	?
szFileName	db	MAX_PATH dup (?)
szFindText	db	100 dup (?)

		.data
stFind		FINDREPLACE <sizeof FINDREPLACE,0,0,FR_DOWN,szFindText,\
		0,sizeof szFindText,0,0,0,0>

		.const
FINDMSGSTRING	db	'commdlg_FindReplace',0
szClassName	db	'Wordpad',0
szCaptionMain	db	'记事本',0
szDllEdit	db	'RichEd20.dll',0
szClassEdit	db	'RichEdit20A',0
szNotFound	db	'字符串未找到!',0
szFilter	db	'Text Files(*.txt)',0,'*.txt',0
		db	'All Files(*.*)',0,'*.*',0,0
szDefaultExt	db	'txt',0
szDefExt	db	'txt',0
szErrOpenFile	db	'无法打开文件!',0
szErrCreateFile	db	'无法建立文件!',0
szModify	db	'文件已修改,是否保存?',0
szFont		db	'宋体',0
szCaption	db	'提问',0
szSaveCaption	db	'请输入保存的文件名',0
szTitleFormat	db	'记事本 - [%s]',0
szNoName	db	'未命名的文件',0
szAboutName	db	'关于本程序',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

		.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 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
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 保存文件,如果没有打开或创建文件则调用“另存为”子程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_SaveFile	proc
		local	@stES:EDITSTREAM

		.if	! hFile
			call	_SaveAs
			.if	! eax
				ret
			.endif
		.endif
		invoke	SetFilePointer,hFile,0,0,FILE_BEGIN
		invoke	SetEndOfFile,hFile

		mov	@stES.dwCookie,FALSE
		mov	@stES.dwError,NULL
		mov	@stES.pfnCallback,offset _ProcStream
		invoke	SendMessage,hWinEdit,EM_STREAMOUT,SF_TEXT,addr @stES
		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
;********************************************************************
; 显示“保存文件”对话框
;********************************************************************
		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_PATHMUSTEXIST
		mov	@stOF.lpstrDefExt,offset szDefExt
		mov	@stOF.lpstrTitle,offset szSaveCaption
		invoke	GetSaveFileName,addr @stOF
		.if	eax
;********************************************************************
; 创建新文件
;********************************************************************
			invoke	CreateFile,addr szFileName,GENERIC_READ or GENERIC_WRITE,\
				FILE_SHARE_READ,0,CREATE_ALWAYS,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 szErrCreateFile,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	@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
;********************************************************************
; 创建文件
;********************************************************************
			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
			invoke	SendMessage,hWinEdit,EM_STREAMIN,SF_TEXT,addr @stES
			invoke	SendMessage,hWinEdit,EM_SETMODIFY,FALSE,0
			call	_SetCaption
		.endif
		ret

_OpenFile	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 允许继续操作则返回TRUE
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_CheckModify	proc

		invoke	SendMessage,hWinEdit,EM_GETMODIFY,0,0
		.if	eax
			invoke	MessageBox,hWinMain,addr szModify,addr szCaption,\
				MB_YESNOCANCEL or MB_ICONQUESTION
			.if	eax ==	IDYES
				call	_SaveFile
			.elseif	eax ==	IDNO
				mov	eax,TRUE
			.elseif	eax ==	IDCANCEL
				xor	eax,eax
			.endif
		.else
			mov	eax,TRUE
		.endif
		ret

_CheckModify	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 查找文字
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_FindText	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
			mov	ecx,hWinMain
			.if	hFindDialog
				mov	ecx,hFindDialog
			.endif
			invoke	MessageBox,ecx,addr szNotFound,NULL,MB_OK or MB_ICONINFORMATION
			ret
		.endif
		invoke	SendMessage,hWinEdit,EM_EXSETSEL,0,addr @stFindText.chrgText
		invoke	SendMessage,hWinEdit,EM_SCROLLCARET,NULL,NULL
		ret

_FindText	endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_SetCaption	proc
		local	@szBuffer[1024]:byte

		.if	szFileName
			mov	eax,offset szFileName
		.else
			mov	eax,offset szNoName
		.endif
		invoke	wsprintf,addr @szBuffer,addr szTitleFormat,eax
		invoke	SetWindowText,hWinMain,addr @szBuffer
		ret

_SetCaption	endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;关于对话框 消息处理过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgAbout	proc	uses ebx edi esi hWnd,wMsg,wParam,lParam
		mov	eax,wMsg
		.if	eax == WM_CLOSE
			invoke	EndDialog,hWnd,NULL
		.elseif	eax == WM_INITDIALOG
			mov eax,TRUE
		.elseif	eax == WM_COMMAND
			mov	eax,wParam
			.if	ax == IDOK
				invoke	EndDialog,hWnd,NULL
			.endif
		.else
			mov	eax,FALSE
			ret
		.endif
		mov	eax,TRUE
		ret

_ProcDlgAbout	endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 关于对话框 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_About proc 
		invoke	DialogBoxParam,hInstance,IDM_ABOUT,hWinMain,offset _ProcDlgAbout,NULL
		ret
_About endp


;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 根据情况改变菜单项状态
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_SetStatus	proc
		local	@stRange:CHARRANGE

		invoke	SendMessage,hWinEdit,EM_EXGETSEL,0,addr @stRange
;********************************************************************
		mov	eax,@stRange.cpMin
		.if	eax ==	@stRange.cpMax
			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	SendMessage,hWinEdit,EM_CANPASTE,0,0
		.if	eax
			invoke	EnableMenuItem,hMenu,IDM_PASTE,MF_ENABLED
		.else
			invoke	EnableMenuItem,hMenu,IDM_PASTE,MF_GRAYED
		.endif
;********************************************************************
		invoke	SendMessage,hWinEdit,EM_CANREDO,0,0
		.if	eax
			invoke	EnableMenuItem,hMenu,IDM_REDO,MF_ENABLED
		.else
			invoke	EnableMenuItem,hMenu,IDM_REDO,MF_GRAYED
		.endif
;********************************************************************
		invoke	SendMessage,hWinEdit,EM_CANUNDO,0,0
		.if	eax
			invoke	EnableMenuItem,hMenu,IDM_UNDO,MF_ENABLED
		.else
			invoke	EnableMenuItem,hMenu,IDM_UNDO,MF_GRAYED
		.endif
;********************************************************************
		invoke	GetWindowTextLength,hWinEdit
		.if	eax
			invoke	EnableMenuItem,hMenu,IDM_SELALL,MF_ENABLED
		.else
			invoke	EnableMenuItem,hMenu,IDM_SELALL,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	szFindText
			invoke	EnableMenuItem,hMenu,IDM_FINDNEXT,MF_ENABLED
			invoke	EnableMenuItem,hMenu,IDM_FINDPREV,MF_ENABLED
		.else
			invoke	EnableMenuItem,hMenu,IDM_FINDNEXT,MF_GRAYED
			invoke	EnableMenuItem,hMenu,IDM_FINDPREV,MF_GRAYED
		.endif
;********************************************************************
		ret

_SetStatus	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Init		proc
		local	@stCf:CHARFORMAT
;********************************************************************
; 注册“查找”对话框消息,初始化“查找”对话框的结构
;********************************************************************
		push	hWinMain
		pop	stFind.hwndOwner
		invoke	RegisterWindowMessage,addr FINDMSGSTRING
		mov	idFindMessage,eax
;********************************************************************
; 建立输出文本窗口
;********************************************************************
		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,0,0,0,\
			hWinMain,0,hInstance,NULL
		mov	hWinEdit,eax

		invoke	SendMessage,hWinEdit,EM_SETTEXTMODE,TM_PLAINTEXT,0
		invoke	RtlZeroMemory,addr @stCf,sizeof @stCf
		mov	@stCf.cbSize,sizeof @stCf
		mov	@stCf.yHeight,9 * 20
		mov	@stCf.dwMask,CFM_FACE or CFM_SIZE or CFM_BOLD
		invoke	_SetCaption
		invoke	lstrcpy,addr @stCf.szFaceName,addr szFont
		invoke	SendMessage,hWinEdit,EM_SETCHARFORMAT,0,addr @stCf
		invoke	SendMessage,hWinEdit,EM_EXLIMITTEXT,0,-1
		ret

_Init		endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_Quit		proc
		invoke	_CheckModify
		.if	eax
			invoke	DestroyWindow,hWinMain
			invoke	PostQuitMessage,NULL
			.if	hFile
				invoke	CloseHandle,hFile
			.endif
		.endif
		ret

_Quit		endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain	proc	uses ebx edi esi hWnd,uMsg,wParam,lParam
		local	@stRange:CHARRANGE
		local	@stRect:RECT

		mov	eax,uMsg
		.if	eax ==	WM_SIZE
			invoke	GetClientRect,hWinMain,addr @stRect
			invoke	MoveWindow,hWinEdit,0,0,@stRect.right,@stRect.bottom,TRUE
;********************************************************************
; 处理菜单、加速键及工具栏消息
;********************************************************************
		.elseif	eax ==	WM_COMMAND
			mov	eax,wParam
			movzx	eax,ax
			.if	eax ==	IDM_NEW
        invoke	_CheckModify
				.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_OPEN
				invoke	_CheckModify
				.if	eax
					call	_OpenFile
				.endif
			.elseif	eax ==	IDM_SAVE
				call	_SaveFile
			.elseif	eax ==	IDM_SAVEAS
				call	_SaveAs
			.elseif	eax ==	IDM_EXIT
				invoke	_Quit
			.elseif	eax ==	IDM_UNDO
				invoke	SendMessage,hWinEdit,EM_UNDO,0,0
			.elseif	eax ==	IDM_REDO
				invoke	SendMessage,hWinEdit,EM_REDO,0,0
			.elseif	eax == IDM_ABOUT
				invoke	_About
			.elseif	eax ==	IDM_SELALL
				mov	@stRange.cpMin,0
				mov	@stRange.cpMax,-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	stFind.Flags,not FR_DIALOGTERM
				invoke	FindText,addr stFind
				.if	eax
					mov	hFindDialog,eax
				.endif
			.elseif	eax ==	IDM_FINDPREV
				and	stFind.Flags,not FR_DOWN
				invoke	_FindText
			.elseif	eax ==	IDM_FINDNEXT
				or	stFind.Flags,FR_DOWN
				invoke	_FindText
			.endif
;********************************************************************
		.elseif	eax ==	WM_INITMENU
			call	_SetStatus
		.elseif	eax ==	idFindMessage
			.if	stFind.Flags & 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
;********************************************************************
		.elseif	eax ==	WM_CREATE
			push	hWnd
			pop	hWinMain
			invoke	_Init
;********************************************************************
		.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,@hRichEdit

		invoke	LoadLibrary,offset szDllEdit
		mov	@hRichEdit,eax
		invoke	GetModuleHandle,NULL
		mov	hInstance,eax
		invoke	LoadMenu,hInstance,IDM_MAIN
		mov	hMenu,eax
		invoke	LoadAccelerators,hInstance,IDA_MAIN
		mov	@hAccelerator,eax
;********************************************************************
; 注册窗口类
;********************************************************************
		invoke	RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
		invoke	LoadIcon,hInstance,ICO_MAIN
		mov	@stWndClass.hIcon,eax
		mov	@stWndClass.hIconSm,eax
		invoke	LoadCursor,0,IDC_ARROW
		mov	@stWndClass.hCursor,eax
		push	hInstance
		pop	@stWndClass.hInstance
		mov	@stWndClass.cbSize,sizeof WNDCLASSEX
		mov	@stWndClass.style,CS_HREDRAW or CS_VREDRAW
		mov	@stWndClass.lpfnWndProc,offset _ProcWinMain
		mov	@stWndClass.hbrBackground,COLOR_BTNFACE+1
		mov	@stWndClass.lpszClassName,offset szClassName
		invoke	RegisterClassEx,addr @stWndClass
;********************************************************************
; 建立并显示窗口
;********************************************************************
		invoke	CreateWindowEx,NULL,\
			offset szClassName,offset szCaptionMain,\
			WS_OVERLAPPEDWINDOW,\
			CW_USEDEFAULT,CW_USEDEFAULT,700,500,\
			NULL,hMenu,hInstance,NULL
		mov	hWinMain,eax
		invoke	ShowWindow,hWinMain,SW_SHOWNORMAL
		invoke	UpdateWindow,hWinMain
;********************************************************************
; 消息循环
;********************************************************************
		.while	TRUE
			invoke	GetMessage,addr @stMsg,NULL,0,0
			.break	.if eax	== 0
			invoke	TranslateAccelerator,hWinMain,@hAccelerator,addr @stMsg
			.if	eax == 0
				invoke	TranslateMessage,addr @stMsg
				invoke	DispatchMessage,addr @stMsg
			.endif
		.endw
		invoke	FreeLibrary,@hRichEdit
		ret

_WinMain	endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
		call	_WinMain
		invoke	ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
		end	start

实现效果如下

当然上面的程序还涉及到资源文件,内容如下:

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include		<resource.h>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define	ICO_MAIN		1000
#define	IDA_MAIN		2000
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define	IDM_MAIN		2000
#define	IDM_NEW			2101
#define	IDM_OPEN		2102
#define	IDM_SAVE		2103
#define	IDM_SAVEAS	2104
#define	IDM_EXIT		2105
#define	IDM_UNDO		2201
#define	IDM_REDO		2202
#define	IDM_SELALL		2203
#define	IDM_COPY		2204
#define	IDM_CUT			2205
#define	IDM_PASTE		2206
#define	IDM_FIND		2207
#define	IDM_FINDPREV	2208
#define	IDM_FINDNEXT	2209
#define	IDM_HELP	3101
#define IDM_ABOUT 3102

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN	ICON		"Main.ico"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IDM_MAIN	menu	discardable
BEGIN
	popup	"文件(&F)"
	BEGIN
	  menuitem	"新建文件(&N)...\tCtrl+N",	IDM_NEW
		menuitem	"打开文件(&O)...\tCtrl+O",	IDM_OPEN
		menuitem	"保存文件(&S)\tCtrl+S",		IDM_SAVE
		menuitem	"文件另存为(&A)...\tCtrl+Alt+S",IDM_SAVEAS
		menuitem	separator
		menuitem	"退出(&X)",		IDM_EXIT
	END
	popup	"编辑(&E)"
	BEGIN
		menuitem	"撤销(&Z)\tCtrl+Z",	IDM_UNDO
		menuitem	"恢复(&Y)\tCtrl+Y",	IDM_REDO
		menuitem	separator
		menuitem	"全选(&A)\tCtrl+A",	IDM_SELALL
		menuitem	"拷贝(&C)\tCtrl+C",	IDM_COPY
		menuitem	"剪切(&X)\tCtrl+X",	IDM_CUT
		menuitem	"粘贴(&V)\tCtrl+V",	IDM_PASTE
		menuitem	separator
		menuitem	"查找(&F)...\tCtrl+F", IDM_FIND
		menuitem	"查找上一个(&P)\tF2", IDM_FINDPREV
		menuitem	"查找下一个(&N)\tF3", IDM_FINDNEXT
	END
	popup	"帮助(&H)"
	BEGIN
		menuitem	"关于(&A)",	IDM_ABOUT
	END
END
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IDA_MAIN	accelerators
BEGIN
		VK_F2,	IDM_FINDPREV,VIRTKEY
		VK_F3,	IDM_FINDNEXT,VIRTKEY
		"N",	IDM_NEW,VIRTKEY,CONTROL
		"O",	IDM_OPEN,VIRTKEY,CONTROL
		"S",	IDM_SAVE,VIRTKEY,CONTROL
		"S",	IDM_SAVEAS,VIRTKEY,CONTROL,ALT
		"Z",	IDM_UNDO,VIRTKEY,CONTROL
		"Y",	IDM_REDO,VIRTKEY,CONTROL
		"A",	IDM_SELALL,VIRTKEY,CONTROL
		"C",	IDM_COPY,VIRTKEY,CONTROL
		"X",	IDM_CUT,VIRTKEY,CONTROL
		"V",	IDM_PASTE,VIRTKEY,CONTROL
		"F",	IDM_FIND,VIRTKEY,CONTROL
END

IDM_ABOUT DIALOG DISCARDABLE  32, 32, 180, 102
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "关于记事本"
FONT 11, "宋体"
BEGIN
    DEFPUSHBUTTON   "确定",IDOK,66,81,50,14
    ICON            ICO_MAIN,-1,7,7,21,20
    CTEXT           "关于本程序",-1,40,12,100,8
    CTEXT           "这是一个记事本程序!",-1,7,40,166,8
    CTEXT           "采用win32汇编语言编写",-1,7,52,166,8
END
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

这个程序看起来,很复杂,实际上,整个exe文件只有10kB,代码细节不想多说,因为涉及面相当广,实现的需求功能如下:

1.文件方面,有新建、保存、另存为、退出。如果内容没有变化,保存菜单呈灰色状态;如果新建文本没有保存时,退出或打开其它文件,提示用户先保存。

2.编辑方面,有撤销、恢复、全选、拷贝、粘贴、查找;

3.帮助方面,只有一个菜单“关于”。

4.当新建文本时,标题栏显示“未命名文件”,如果是打开的文件,则显示此文件路径及文件名。

 

win32汇编虽然不及现在的web编程那么流行,但对操作系统的理解却很有帮助,有利于解决一些电脑上出现的问题,特别是系统安全方面,如病毒、软件破解这些。

转载于:https://my.oschina.net/moluyingxing/blog/820787

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值