;Win02.ASM : Menu From A Resource File (October 1, 2023)

%ifdef ;see Note at end.

   The " %include " paths at the start of the file might need to be
       changed to suit your own disk directory setup.
    Command Lines:
    Assembly: nasm -f win32 win02.asm -o win02.obj;
	Resource : rc win02.rc
    Link:  golink.exe /entry:start win02.obj win02.res kernel32.dll user32.dll

%endif


;INCLUDE FILES  

%include '\nasm32\inc\win32\windows.inc'
%include '\nasm32\inc\win32\kernel32.inc'
%include '\nasm32\inc\win32\user32.inc'
%include '\nasm32\inc\nasm32.inc'

;							-------------
;								DATA
;							-------------

[section .data]

;MENU EQUATES

Win02_Menu equ 100 	;This label name can be anything at all as long as it matches
					;the entry for .lpszMenuName AND equates to 100.
IDM_EXIT equ 104   	;Ditto here

;HANDLES

hInstance dd 0
hWnd dd 0
hMenu dd 0

;VARIOUS LABELS

szTitle db 'win02 : A Simple NASM Window With A Menu From A Resource (.RC) File',0x0
szClass db 'win02 Class',0x0

;STRUCS

wcx  times WNDCLASSEX_size dd 0	;Declare a memory block of WNDCLASSEX size.
msg times MSG_size dd 0			;Declare a memory block of MSG size.

;							-------------
;								CODE
;							-------------

[section .text]

	start:          ;Start point for GoLink.exe


	proc Win02
		invoke GetModuleHandleA, dword NULL
		mov [hInstance], eax
		invoke WinMain,dword [hInstance],dword NULL,dword NULL,dword SW_SHOWNORMAL
		invoke ExitProcess,dword NULL
	ret
	endproc ;win02

;WinMain

	proc WinMain ,hInst,hPinst,CmdLn,dwShow

;Memory block reserved for wcx [WNDCLASSEX] has no data yet. 

push dword WNDCLASSEX_size
pop dword [wcx  + WNDCLASSEX.cbSize]

push dword argv(hInst)      
pop dword [wcx  + WNDCLASSEX.hInstance]

push dword szClass
pop dword [wcx  + WNDCLASSEX.lpszClassName]

push dword WndProc    ; Adr of WndProc
pop dword [wcx  + WNDCLASSEX.lpfnWndProc]

push dword COLOR_BTNFACE +1
pop dword [wcx  + WNDCLASSEX.hbrBackground]

push dword CS_VREDRAW +CS_HREDRAW
pop dword [wcx  + WNDCLASSEX.style]

push dword Win02_Menu ;szMenuName
pop dword [wcx  + WNDCLASSEX.lpszMenuName]

		invoke RegisterClassExA, dword wcx 

;Create Window

		invoke CreateWindowExA,\
		WS_EX_OVERLAPPEDWINDOW,\
						szClass,\
						szTitle,\
		WS_OVERLAPPEDWINDOW +WS_VISIBLE ,\
				50, 50, 600, 200,\
							NULL,\
						NULL,\
						dword [hInstance],\
						NULL
		mov [hWnd], eax	

;Process Windows Messages

	MsgGet:
		invoke GetMessageA, dword msg, dword NULL, dword NULL, dword NULL
   	    cmp eax,0
   	       jnz MsgProcess
		jmp MsgEnd
	MsgProcess:
		invoke TranslateMessage, dword msg
   		invoke DispatchMessageA, dword msg
   		jmp MsgGet
	MsgEnd:
		mov eax,[msg +MSG.wParam]
ret
	endproc ;WinMain

;WndProc

	proc WndProc, hWin, uMsg, wParam, lParam

		cmp dword argv(uMsg),dword WM_KEYDOWN
			jnz IsCommand?

;Msg =WM_KEYDOWN

			cmp dword argv(wParam),VK_ESCAPE	;Esc key?
				jz CloseWindow
			xor eax,eax
ret

;wParam =ESC

				CloseWindow:
				invoke SendMessageA,dword argv(hWin),WM_CLOSE,NULL,NULL
				xor eax,eax
ret

		IsCommand?:
		cmp dword argv(uMsg),WM_COMMAND
			jnz IsDestroy?

;Msg =WM_COMMAND

		mov eax, dword argv(wParam)	
		shr eax,10h				; Hi 16 into AX. AX =0 =Menu 
		cmp ax,0
			jz IsMenu
		xor eax,eax			;Not a menu event so WM_COMMAND parameter
							;is of no interest to us. Just Return 
ret							

;WM_COMMAND ((wParam(Hi 16 bits))=Menu

			IsMenu:        
				cmp dword argv(wParam),IDM_EXIT ;((wParam(Hi 16)) =0 so DWORD argv 
					jz CloseWindow				;    will trap  on wParam(Lo 16)
				xor eax,eax
ret

		IsDestroy?:		
		cmp dword argv(uMsg), WM_DESTROY
			jnz DefWndProc	; No message for us so pass it to DefWndProc 
			
;WM_DESTROY Msg

		invoke PostQuitMessage,dword NULL
		xor eax,eax
ret

;DefWndProc


	DefWndProc:
	invoke DefWindowProcA, dword argv(hWin), dword argv(uMsg),\
						dword argv(wParam),dword argv(lParam)
ret
endproc     ;WndProc

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

%ifdef
Notes On %ifdef/%endif Used As A Block Comment Tool.

The use of %ifdef / %endif creates a phony conditional assembly block which
will fail at compile time due to incorrect syntax (whatever text follows 
the %ifdef / %endif won't have been predefined). Thus, all content between
the statements will be ignored. This enables us to use the block as a comment 
section without the cumbersome necessity of preceding every line with a semicolon.
Thanks and a tip of the hat to Frank Kotler.
%endif

;mcamember May 9, 2024