I thought I would post this as it is my commented version of tutorial#3 of eczelions tutorials. I know he did a fairly good job of explaining it but I have put some debug stuff that i got from this message board and also tried to explain how I believe the program is running. I know it looks a bit messy, hopefully it will still explain the process though
.386 ;This is the Machine type
.model flat,stdcall ;This is the syntax to use for calls
option casemap:none ;This allows the keys to be case sensitive
include windows.inc ;various include bits
includelib kernel32.lib ;and there associated libraries
;have to define the prototype before calling it as a procedure.
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
.CONST ;numerical variables that don't change.
; DBUG equ 1 ;we uncomment this to run debug instructions on the program
AppName db "An Application",0 ;String variables that don't change
ClassName db "A Class Name",0 ;always finish with a terminating 0 as
ErrorHandle db "Incorrect Parent Handle",0 ;it is in ascii format
ErrorMsgBoxTitle db "Critical Error",0
ErrorWindow db "Could not create or update the window",0
hInstance HINSTANCE ? ;strings that change
CommandLine LPSTR ?
.code ;start of code section
start: ;our first label
invoke GetModuleHandle,NULL ;grab the handle for our module
mov hInstance,eax ;put it into hInstance
invoke GetCommandLine ;grab the command line
mov CommandLine,eax ;put it in CommandLine
invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT ;invoke our procedure
invoke ExitProcess,eax ;then exit
;this is the beginning of our procedure
WinMain proc hInst:HINSTANCE,
LOCAL wc:WNDCLASSEX ;set up local variables. wc is our windows class, msg is the messenger variable
LOCAL msg:MSG ;and hWnd is the handle of our Main Window.
mov wc.cbSize,SIZEOF WNDCLASSEX ;set the variables for the wc class
mov wc.lpfnWndProc,OFFSET WinProc
mov wc.lpszClassName,OFFSET ClassName
invoke RegisterClassEx,addr wc ;register our class
invoke CreateWindowEx, ;begin the creation of the window
NULL, ;this will give us our window handle
mov hWnd,eax ;place the handle in hWnd
invoke ShowWindow,hWnd,SW_SHOWNORMAL ;make the window visible
invoke UpdateWindow,hWnd ;keep the window refreshed
;**** The window doesn't display if the procedure is not running
IFDEF DBUG ;This section is only attached to the code if the DBUG variable is defined. ;debug section only
;used to check for errors
.IF !EAX ;execute next instruction if there was an error creating the window
INVOKE MessageBox,ESI,addr ErrorWindow,addr ErrorMsgBoxTitle,MB_OK ;message and exit if failure
JMP EXIT ;after creating a notification box we jump to the exit
ENDIF ;not that the . in front of IF means it is run at run time. No . means it is run at assembly time
.WHILE TRUE ;enter the message loop
invoke GetMessage,addr msg,NULL,0,0 ;get our message. usually wm_paint first up.
IFDEF DBUG ;more debug script.. only gets assembled if we create the variable DBUG
.IF eax==-1 ;another way of checking for values. check to see if eax is -1
invoke MessageBox, NULL,addr ErrorHandle,addr ErrorMsgBoxTitle, MB_OK
JMP EXIT ;invoke a message box and exit
ENDIF ;end of our debug section which was used to check if there was an error in the window handle.
.BREAK .IF (!EAX) ;this is realtime code.. breaks the loop if eax is 0. i.e. program is finished.
invoke TranslateMessage, ADDR msg ;translate message to ansi code.
invoke DispatchMessage, ADDR msg ; dispatch the message and run the procedure
mov eax,msg.wParam ;load the message for the exit process
.ENDW ;I'm not sure if this is how the procedure is run.. i'm just guessing at present.
EXIT: ;our exit label.. so that we can jump to the end of the loop if there is an error.
ret ;return to the calling function.. i.e. top of this program after invoke WinMain. The next line is invoke exitprocess
WinMain endp ;the end of our WinMain procedure.. this probably never really gets executed.
WinProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM ;the start of the window procedure
.IF uMsg==WM_DESTROY ;if we got the exit message from getmessage in WinMain.
invoke PostQuitMessage,NULL ;then we invoke the quitmessage grabber
.ELSE ;otherwise we run the default window cleaning stuff which takes care of all the
invoke DefWindowProc,hWnd,uMsg,wParam,lParam ;other messages.
ret ;then we return to WinMain..
.ENDIF ;if we use post quitmessage we will end up here to exit the loop.
xor eax,eax ;after recieving the post quit message, we execute a zero out of eax. I.E. this makes it 0
ret ;then we return control to WinMain So that it can exit, because it has a 0 message.
WinProc endp ;this is just the end of the procedure
end start ;and this is the end of our program, that displayed a window.