;================================codes by guokeno1--逐行注释!看了你会说这东西真爽================================;
.386
.model flat,stdcall
option casemap:none
include d:/masm32/oop/jeffoop/oop.inc;关于这个东西的原代码参见我上一篇文字
include d:/masm32/include/windows.inc
include d:/masm32/include/kernel32.inc
includelib d:/masm32/lib/kernel32.lib
include d:/masm32/include/user32.inc
includelib d:/masm32/lib/user32.lib
CLASS AWINDOW;声明CLASS,CLASS原型实际为STRUCT
METHOD AWINDOW_init,LPCLASSNAME,LPTITLE;声明构造器,METHOD宏实际是定义了一个两个参数的函数指针
@WC WNDCLASSEX <>;这个是WNDCLASSEX结构,也算是一个成员吧
@HWND MEMBER ?;这个是建立的窗口的句柄
@HINSTANCE MEMBER ?;这个是程序句柄
@HEIGHT MEMBER ?;高度
@WIDTH MEMBER ?;宽度
@LEFT MEMBER ?;左上角X
@TOP MEMBER ?左上角Y
@CLASSNAME MEMBER ?;窗口类名子
@TITLE MEMBER ?;标题
@MSG MSG <>;MSG消息结构,也算做成员
VIRTUAL V_WNDPROC;虚函数,利用这个可以重载窗口的回调函数
METHOD BUILDWINDOW,CMD_LINE,CMD_SHOW;BUILDWINDOW方法,用来创建窗口
AWINDOW ENDC
.data
hProcess dd ?
lpWindow dd ?
.code
;================================codes for AWINDOW在这里定义方法的实体================================;
AWINDOW_WNDPROCA PROC hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
AWINDOW_WNDPROCA ENDP
AWINDOW_BUILDWINDOW PROC USES EBX EDI ESI CMD_LINE:DWORD,CMD_SHOW:DWORD
GETCLASS AWINDOW;把EBX设置为AWINDOW类型的指针
;由于在进入函数前已经把类的指针放入EBX,所以EBX相当与THIS指针
;下面的这些乱七八糟的东西其实就是注册并显示窗体的过程
;填充@WC成员以便注册窗口类:
MOV [EBX].@WC.cbSize,sizeof WNDCLASSEX
MOV [EBX].@WC.style,CS_HREDRAW OR CS_VREDRAW
MOV EAX,[EBX].V_WNDPROC
MOV [EBX].@WC.lpfnWndProc,EAX
MOV [EBX].@WC.cbClsExtra,0
MOV [EBX].@WC.cbWndExtra,0
MOV EAX,[EBX].@HINSTANCE
MOV [EBX].@WC.hInstance,EAX
MOV [EBX].@WC.lpszMenuName,0
MOV EAX,[EBX].@CLASSNAME
MOV [EBX].@WC.lpszClassName,EAX
MOV [EBX].@WC.hbrBackground,COLOR_WINDOW+1
invoke LoadIcon,0,IDI_APPLICATION
mov [EBX].@WC.hIcon,eax
mov [EBX].@WC.hIconSm,eax
invoke LoadCursor,0,IDC_ARROW
mov [EBX].@WC.hCursor,eax
GETADDR @WC;得到@WC的指针,GETADDR宏返回在EDI中
invoke RegisterClassEx,EDI;注册
;创建窗口
invoke CreateWindowEx,0,[EBX].@CLASSNAME,[EBX].@TITLE,WS_OVERLAPPEDWINDOW,/
[EBX].@LEFT,[EBX].@TOP,[EBX].@WIDTH,[EBX].@HEIGHT,/
0,0,[EBX].@HINSTANCE,0
MOV [EBX].@HWND,EAX
INVOKE ShowWindow,[EBX].@HWND,CMD_SHOW;显示
INVOKE UpdateWindow,[EBX].@HWND
.WHILE TRUE
GETADDR @MSG
INVOKE GetMessage,EDI,0,0,0
.BREAK .IF(!EAX)
INVOKE TranslateMessage,EDI
INVOKE DispatchMessage,EDI
.ENDW
MOV EAX,1
RET
RELEASECLASS
AWINDOW_BUILDWINDOW ENDP
AWINDOW_init proc USES EBX EDI ESI LPCLASSNAME:DWORD,LPTITLE:DWORD;构造齐
GETCLASS AWINDOW
;这个是构造器定义的一般格式,NEW宏的构造是先HEAPALLOC一块内存,这块内存就是我们类的生存空间
INVOKE RtlZeroMemory,ebx,sizeof AWINDOW;首先清空所有成员
MOV EAX,LPCLASSNAME
MOV [EBX].@CLASSNAME,EAX;设定@CLASSNAME
MOV EAX,LPTITLE;
MOV [EBX].@TITLE,EAX;设定@TITLE
MOV EAX,AWINDOW_BUILDWINDOW
MOV [EBX].BUILDWINDOW,EAX;设定BUILDWINDOW的指针位置,注意我们只能在构造器中添入成员门的预定指针,在别的地方有悖于面向对象的思想
MOV EAX,hProcess
MOV [EBX].@HINSTANCE,EAX;@HINSTANCE成员
MOV [EBX].AWINDOW_init,AWINDOW_init;最后象征性的添入构造器地址(其实不填根本没事,为了规范)
RET
RELEASECLASS;把EBX的指针类型设置为NOTHING
AWINDOW_init endp
;================================function main====================================;
MAIN:
invoke GetModuleHandle,0
MOV hProcess,EAX
;STRING是我定义的宏,用来返回一个常量字符串的指针,真的很方便的说
;向构造器传入参数并构造类,返回类的指针在EBX中
;NEW宏的构造为:先分配内存,再调用构造器
NEW AWINDOW,STRINGA("SIMPLE WINDOW"),STRINGA("WINDOW CLASS")
MOV lpWindow,EBX
GETCLASS AWINDOW;设置EBX的指针类型为AWINDOW
OVERRIDE V_WNDPROC,AWINDOW_WNDPROCA;重载虚函数使之指向我的AWINDOW_WNDPROCA过程
MOV [EBX].@LEFT,CW_USEDEFAULT
MOV [EBX].@TOP,CW_USEDEFAULT
MOV [EBX].@WIDTH,CW_USEDEFAULT
MOV [EBX].@HEIGHT,CW_USEDEFAULT
EXERT BUILDWINDOW,0,SW_SHOWDEFAULT;调用方法,建立窗体,EXERT和INVOKE异曲同工之妙,但是EXERT可以直接CALL一个地址,而INVOKE只能CALL函数指针,所以只能用EXERT
RELEASECLASS
invoke ExitProcess,0
END MAIN
【 在 joshuaG 的大作中提到: 】
: 主要是,看不明白这些代码……
: 能写点解释不~~
: 【 在 raywill (晓楚) 的大作中提到: 】
: : 不否认C++,JAVA,C#甚至的好,也决不放弃WIN32ASM太多的事C干不了,太多的事ASM麻烦...
: : ...这次使用面向对象是想对ASM的代码重用问题做个了断
: :
: :