第一部分 窗口和消息处理
WinMain函数(应用程序入口)
WinMain proc hInst :DWORD,
hPrevInst :DWORD,
CmdLine :DWORD,
CmdShow :DWORD
;====================
; Put LOCALs on stack
;====================
LOCAL wc :WNDCLASSEX
LOCAL msg :MSG
LOCAL Wwd :DWORD
LOCAL Wht :DWORD
LOCAL Wtx :DWORD
LOCAL Wty :DWORD
;==================================================
; Fill WNDCLASSEX structure with required variables
;==================================================
invoke LoadIcon,hInst,1 ; icon ID
mov hIcon, eax
szText szClassName,"bmbtn_Class"
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW \
or CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc, offset WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance, hInst
mov wc.hbrBackground, COLOR_BTNFACE+1
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, offset szClassName
m2m wc.hIcon, hIcon
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor, eax
m2m wc.hIconSm, hIcon
invoke RegisterClassEx, ADDR wc
;================================
; Centre window at following size
;================================
mov Wwd, 250
mov Wht, 150
invoke GetSystemMetrics,SM_CXSCREEN
invoke TopXY,Wwd,eax
mov Wtx, eax
invoke GetSystemMetrics,SM_CYSCREEN
invoke TopXY,Wht,eax
mov Wty, eax
invoke CreateWindowEx,WS_EX_LEFT,
ADDR szClassName,
ADDR szDisplayName,
WS_OVERLAPPED or WS_SYSMENU,
Wtx,Wty,Wwd,Wht,
NULL,NULL,
hInst,NULL
mov hWnd,eax
invoke LoadMenu,hInst,600 ; menu ID
invoke SetMenu,hWnd,eax
invoke ShowWindow,hWnd,SW_SHOWNORMAL
invoke UpdateWindow,hWnd
;===================================
; Loop until PostQuitMessage is sent
;===================================
StartLoop:
invoke GetMessage,ADDR msg,NULL,0,0
cmp eax, 0
je ExitLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp StartLoop
ExitLoop:
return msg.wParam
WinMain endp
窗口过程函数(WndProc)
WndProc proc hWin :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
LOCAL var :DWORD
LOCAL caW :DWORD
LOCAL caH :DWORD
LOCAL Rct :RECT
LOCAL hDC :DWORD
LOCAL Ps :PAINTSTRUCT
LOCAL buffer1[128]:BYTE ; these are two spare buffers
LOCAL buffer2[128]:BYTE ; for text manipulation etc..
.if uMsg == WM_COMMAND
.if wParam == 400
.endif
;======== menu commands ========
.elseif uMsg == WM_CREATE
.elseif uMsg == WM_SIZE
.elseif uMsg == WM_PAINT
invoke BeginPaint,hWin,ADDR Ps
mov hDC, eax
invoke Paint_Proc,hWin,hDC
invoke EndPaint,hWin,ADDR Ps
return 0
.elseif uMsg == WM_CLOSE
.elseif uMsg == WM_DESTROY
invoke PostQuitMessage,NULL
return 0
.endif
invoke DefWindowProc,hWin,uMsg,wParam,lParam
ret
WndProc endp
注册窗口类过程
RegisterWinClass proc lpWndProc:DWORD, lpClassName:DWORD,
Icon:DWORD, Cursor:DWORD, bColor:DWORD
LOCAL wc:WNDCLASSEX
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_BYTEALIGNCLIENT or \
CS_BYTEALIGNWINDOW
m2m wc.lpfnWndProc, lpWndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance, hInstance
m2m wc.hbrBackground, bColor
mov wc.lpszMenuName, NULL
m2m wc.lpszClassName, lpClassName
m2m wc.hIcon, Icon
m2m wc.hCursor, Cursor
m2m wc.hIconSm, Icon
invoke RegisterClassEx, ADDR wc
ret
RegisterWinClass endp
消息循环过程
MsgLoop proc
; ------------------------------------------
; The following 4 equates are available for
; processing messages directly in the loop.
; m_hWnd - m_Msg - m_wParam - m_lParam
; ------------------------------------------
LOCAL msg:MSG
StartLoop:
invoke GetMessage,ADDR msg,NULL,0,0
cmp eax, 0
je ExitLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp StartLoop
ExitLoop:
mov eax, msg.wParam
ret
MsgLoop endp
对话框窗口过程
dlgproc proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
.if uMsg == WM_INITDIALOG
invoke SendMessage,hWin,WM_SETICON,1,FUNC(LoadIcon,NULL,IDI_ASTERISK)
.elseif uMsg == WM_COMMAND
.if wParam == IDCANCEL
jmp quit_dialog
.endif
.elseif uMsg == WM_CLOSE
quit_dialog:
invoke EndDialog,hWin,0
.endif
xor eax, eax
ret
dlgproc endp
第二部分 控件
按钮过程
BtnProc proc hCtl :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
.if uMsg == WM_KEYDOWN
jmp lbd
.elseif uMsg == WM_KEYUP
jmp lbu
.elseif uMsg == WM_LBUTTONDOWN
lbd:
invoke LoadIcon,hInstance,3
invoke SendMessage,hBtn2,BM_SETIMAGE,1,eax
.elseif uMsg == WM_LBUTTONUP
lbu:
invoke LoadIcon,hInstance,2
invoke SendMessage,hBtn2,BM_SETIMAGE,1,eax
.endif
invoke CallWindowProc,lpBtnProc,hCtl,uMsg,wParam,lParam
ret
BtnProc endp
图标按钮过程
IconButton proc hParent:DWORD,a:DWORD,b:DWORD,wd:DWORD,ht:DWORD,ID:DWORD
; IconButton PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
; invoke IconButton,hWnd,20,20,100,25,500
szText icoBtnCl,"BUTTON"
szText blnk1,0
invoke CreateWindowEx,0,
ADDR icoBtnCl,ADDR blnk1,
WS_CHILD or WS_VISIBLE or BS_ICON,
a,b,wd,ht,hParent,ID,
hInstance,NULL
ret
IconButton endp
位图按钮过程
BmpButton proc hParent:DWORD,a:DWORD,b:DWORD,wd:DWORD,ht:DWORD,ID:DWORD
; BmpButton PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
; invoke BmpButton,hWnd,20,20,100,25,500
szText bmpBtnCl,"BUTTON"
szText blnk2,0
invoke CreateWindowEx,0,
ADDR bmpBtnCl,ADDR blnk2,
WS_CHILD or WS_VISIBLE or BS_BITMAP,
a,b,wd,ht,hParent,ID,
hInstance,NULL
ret
BmpButton endp
创建列表框
ListBox proc a:DWORD,b:DWORD,wd:DWORD,ht:DWORD,hParent:DWORD,ID:DWORD
szText lstBox,"LISTBOX"
invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR lstBox,0,
WS_VSCROLL or WS_VISIBLE or \
WS_BORDER or WS_CHILD or \
LBS_HASSTRINGS or LBS_NOINTEGRALHEIGHT or \
LBS_DISABLENOSCROLL,
a,b,wd,ht,hParent,ID,hInstance,NULL
ret
ListBox endp
列表框消息处理过程
ListBoxProc proc hCtl :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
LOCAL IndexItem :DWORD
LOCAL Buffer[32] :BYTE
.if uMsg == WM_LBUTTONDBLCLK
jmp DoIt
.elseif uMsg == WM_CHAR
.if wParam == 13
jmp DoIt
.endif
.endif
jmp EndDo
DoIt:
invoke SendMessage,hCtl,LB_GETCURSEL,0,0
mov IndexItem, eax
invoke SendMessage,hCtl,LB_GETTEXT,IndexItem,ADDR Buffer
mov eax, hList1
.if hCtl == eax
szText CurSel1,"You selected from hList1"
invoke MessageBox,hWnd,ADDR Buffer,ADDR CurSel1,MB_OK
.else
szText CurSel2,"You selected from hList2"
invoke MessageBox,hWnd,ADDR Buffer,ADDR CurSel2,MB_OK
.endif
EndDo:
invoke CallWindowProc,lpLstBox1,hCtl,uMsg,wParam,lParam
ret
ListBoxProc endp
创建工具条
Do_ToolBar proc hWin :DWORD
LOCAL bSize :DWORD
LOCAL tbab :TBADDBITMAP
LOCAL tbb :TBBUTTON
; ------------------------
; Uncomment following when
; bitmap has been created
; ------------------------
; invoke LoadBitmap,hInstance,750
; mov hTbBmp,eax
; --------------------------------------------------
; Set toolbar button dimensions here, width & height
; --------------------------------------------------
Create_Tool_Bar 25, 25
TBextraData ; additional data for TBBUTTON structure
; -----------------------------------
; Add toolbar buttons and spaces here
; Syntax for the macro TBbutton is
; TBbutton bmpID number, WM_COMMAND ID number
; WM_COMMAND ID numbers start at 50
; -----------------------------------
TBblank
TBbutton 0, 50
; TBbutton 1, 51
; TBbutton 2, 52
; TBblank
; TBbutton 3, 53
; TBbutton 4, 54
; TBbutton 5, 55
; TBblank
; TBbutton 6, 56
; TBbutton 7, 57
; TBbutton 8, 58
ret
Do_ToolBar endp
第三部分
第四部分
第五部分 GDI、坐标、绘图
获取中点坐标
TopXY proc wDim:DWORD, sDim:DWORD
shr sDim, 1 ; divide screen dimension by 2
shr wDim, 1 ; divide window dimension by 2
mov eax, wDim ; copy window dimension into eax
sub sDim, eax ; sub half win dimension from half screen dimension
return sDim
TopXY endp
绘图过程
Paint_Proc proc hWin:DWORD, hDC:DWORD
LOCAL btn_hi :DWORD
LOCAL btn_lo :DWORD
LOCAL Rct :RECT
invoke GetSysColor,COLOR_BTNHIGHLIGHT
mov btn_hi, eax
invoke GetSysColor,COLOR_BTNSHADOW
mov btn_lo, eax
return 0
Paint_Proc endp
第六部分
第七部分
第八部分 字符串操作
填充缓冲区
FillBuffer proc lpBuffer:DWORD,lenBuffer:DWORD,TheChar:BYTE
push edi
mov edi, lpBuffer ; address of buffer
mov ecx, lenBuffer ; buffer length
mov al, TheChar ; load al with character
rep stosb ; write character to buffer until ecx = 0
pop edi
ret
FillBuffer endp
第九部分 文件操作
得到打开的文件名
GetFileName proc hParent:DWORD,lpTitle:DWORD,lpFilter:DWORD
mov ofn.lStructSize, sizeof OPENFILENAME
m2m ofn.hWndOwner, hParent
m2m ofn.hInstance, hInstance
m2m ofn.lpstrFilter, lpFilter
m2m ofn.lpstrFile, offset szFileName
mov ofn.nMaxFile, sizeof szFileName
m2m ofn.lpstrTitle, lpTitle
mov ofn.Flags, OFN_EXPLORER or OFN_FILEMUSTEXIST or \
OFN_LONGNAMES
invoke GetOpenFileName,ADDR ofn
ret
GetFileName endp
保存文件名
SaveFileName proc hParent:DWORD,lpTitle:DWORD,lpFilter:DWORD
mov ofn.lStructSize, sizeof OPENFILENAME
m2m ofn.hWndOwner, hParent
m2m ofn.hInstance, hInstance
m2m ofn.lpstrFilter, lpFilter
m2m ofn.lpstrFile, offset szFileName
mov ofn.nMaxFile, sizeof szFileName
m2m ofn.lpstrTitle, lpTitle
mov ofn.Flags, OFN_EXPLORER or OFN_LONGNAMES
invoke GetSaveFileName,ADDR ofn
ret
SaveFileName endp
读磁盘文件
read_diskfile proc lpName:DWORD,lpMem:DWORD
LOCAL hFile :DWORD
LOCAL fl :DWORD
LOCAL bRead :DWORD
LOCAL Mem :DWORD
invoke CreateFile,lpName,GENERIC_READ,0,NULL,OPEN_EXISTING,NULL,NULL
mov hFile, eax
invoke GetFileSize,hFile,NULL
mov fl, eax
; -----------------------
; allocate string memory
; -----------------------
invoke SysAllocStringByteLen,0,fl
mov Mem, eax
; ---------------------------------------------------
; write handle to DWORD variable passed as parameter
; ---------------------------------------------------
mov ecx, lpMem
mov [ecx], eax
invoke ReadFile,hFile,Mem,fl,ADDR bRead,NULL
invoke CloseHandle,hFile
; -------------------------
; return bytes read in EAX
; -------------------------
mov eax, bRead
ret
read_diskfile endp
写磁盘文件
disk_write proc lpName:DWORD,lpData:DWORD,fl:DWORD
LOCAL hOutput:DWORD
LOCAL bw :DWORD
invoke CreateFile,lpName,GENERIC_WRITE,NULL,NULL,
CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL
mov hOutput, eax
invoke WriteFile,hOutput,lpData,fl,ADDR bw,NULL
invoke CloseHandle,hOutput
mov eax, bw ; return written byte count
ret
disk_write endp
文件搜索过程
SearchForFile PROC StartPath:DWORD,FileToFind:DWORD
LOCAL WFD:WIN32_FIND_DATA ; used for file/folder search
LOCAL fPath[260]:BYTE ; used to store StartPath locally
LOCAL fPath2[260]:BYTE ; we add sub-folders names onto this to form full paths
LOCAL hFind:DWORD ; find handle
; Below is just some little data's that we need in order for function to work
jmp @F
WildCard db "\*",0 ; search ALL files
CRLF db 13,10,0 ; tell me you don't know what this is
foundat db "Found: ",0 ; tell the user we found a file that matches
@@:
lea edi,fPath
push edi ; save EDI in stack
mov esi,StartPath ; we are copying supplied StartPath to our buffer
mov ecx,256 ; all 256 bytes
rep movsb ; copy path
pop edi ; put the path back in EDI
xor al,al ; clear AL
@GetToChar ; Find the first zero
mov al,'\' ; now equals Drive:\Path\*
stosb ; e.g.: C:\Windows\*
mov al,'*'
stosb
@ClearFN ; clears the cFileName field in Win32_Find_Data
invoke FindFirstFile,addr fPath,addr WFD ; find first file
push eax ;
mov hFind,eax ; save FindHandle
pop ebx ; put handle in EBX
.while ebx > 0 ; while a file is found..
lea esi,WFD.cFileName
lodsw ; get first two chars
.if AX!=02E2Eh && AX!=0002Eh ; '..' and '.'
lea edi,WFD
mov eax,[edi] ; file attributes
.if ax & FILE_ATTRIBUTE_DIRECTORY ; is it a directory?
sub esi,2 ; undo the lodsw
lea edi,fPath2 ; load up the secondary path in EDI
push edi ; save it on the stack...
xor al,al ; clear secondary path
mov ecx,260 ; ..
rep stosb
mov edi,[esp] ; restore EDI
lea eax,fPath ; first path
invoke lstrcpy,edi,eax ; copy first to second
mov al,'*' ; get to the end....
@GetToChar
mov byte ptr [edi],00h ; delete the wildcard
invoke lstrcat,edi,esi ; tack on the new directory name
pop edi ; restore EDI from stack
pushad ; must save ALL regs or errors will ocur :)
invoke SearchForFile,edi,FileToFind ; call function again
popad ; restore all regs
.else
sub esi,2 ; undo the lodsw
invoke lstrcmpi,FileToFind,esi ; case insensitive compare
or eax,eax ; are they equal?
jz found_file ; if eax=0 they are equal
.endif
.endif
@ClearFN ; Clear the cFileName field again
invoke FindNextFile,hFind,addr WFD
mov ebx,eax
.endw
__cls_fnd:
invoke FindClose,hFind ; close it up
ret
found_file: ; we found a file, so we report it to the user
lea edi,fPath2
invoke lstrcpy,edi,addr fPath
mov al,'*'
scasb
jnz $-1
dec edi
mov byte ptr [edi],00h
lea edi,WFD.cFileName
invoke lstrcat,addr fPath2,edi
invoke StdOut,addr foundat
invoke StdOut,addr fPath2
invoke StdOut,addr CRLF
jmp __cls_fnd
SearchForFile ENDP
第十部分 图形和位图
设置位图颜色
SetBmpColor proc hBitmap:DWORD
LOCAL mDC :DWORD
LOCAL hBrush :DWORD
LOCAL hOldBmp :DWORD
LOCAL hReturn :DWORD
LOCAL hOldBrush :DWORD
invoke CreateCompatibleDC,NULL
mov mDC,eax
invoke SelectObject,mDC,hBitmap
mov hOldBmp,eax
invoke GetSysColor,COLOR_BTNFACE
invoke CreateSolidBrush,eax
mov hBrush,eax
invoke SelectObject,mDC,hBrush
mov hOldBrush,eax
invoke GetPixel,mDC,1,1
invoke ExtFloodFill,mDC,1,1,eax,FLOODFILLSURFACE
invoke SelectObject,mDC,hOldBrush
invoke DeleteObject,hBrush
invoke SelectObject,mDC,hBitmap
mov hReturn,eax
invoke DeleteDC,mDC
mov eax,hReturn
ret
SetBmpColor endp
位图过程
bmpProc proc hCtl :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
.if uMsg == WM_KEYDOWN
jmp lbda
.elseif uMsg == WM_KEYUP
jmp lbua
.elseif uMsg == WM_LBUTTONDOWN
lbda:
invoke SendMessage,hBtn4,BM_SETIMAGE,0,hBmp2
.elseif uMsg == WM_LBUTTONUP
lbua:
invoke SendMessage,hBtn4,BM_SETIMAGE,0,hBmp1
.endif
invoke CallWindowProc,lpfnbmpProc,hCtl,uMsg,wParam,lParam
ret
bmpProc endp
第二十部分 常用宏
insert TEXT into the code section
szText MACRO Name, Text:VARARG
LOCAL lbl
jmp lbl
Name db Text,0
lbl:
ENDM
copy from one memory location to another
m2m MACRO M1, M2
push M2
pop M1
ENDM
return宏
return MACRO arg
mov eax, arg
ret
ENDM