.386
.model
flat,stdcall
option
casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include
\masm32\include\windows.inc
include
\masm32\include\user32.inc
include
\masm32\include\kernel32.inc
includelib
\masm32\lib\user32.lib
includelib
\masm32\lib\kernel32.lib
.data
ClassName
db "SimpleWinClass",0
AppName
db "Our First Window",0
MenuName
db "FirstMenu",0
; The name of our menu in the resource file.
Test_string
db "You selected Test menu item",0
Hello_string
db "Hello, my friend",0
Goodbye_string
db "See you again, bye",0
.data?
hInstance
HINSTANCE ?
CommandLine
LPSTR ?
.const
IDM_TEST
equ 1
; Menu IDs
IDM_HELLO
equ 2
IDM_GOODBYE
equ 3
IDM_EXIT
equ 4
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain
proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,OFFSET MenuName
; Put our menu name here
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain
endp
WndProc
proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF ax==IDM_TEST
invoke MessageBox,NULL,ADDR Test_string,OFFSET AppName,MB_OK
.ELSEIF ax==IDM_HELLO
invoke MessageBox, NULL,ADDR Hello_string, OFFSET AppName,MB_OK
.ELSEIF ax==IDM_GOODBYE
invoke MessageBox,NULL,ADDR Goodbye_string, OFFSET AppName, MB_OK
.ELSE
invoke DestroyWindow,hWnd
.ENDIF
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc
endp
end start
**************************************************************************************************************************
#define
IDM_TEST 1
#define
IDM_HELLO 2
#define
IDM_GOODBYE 3
#define
IDM_EXIT 4
FirstMenu
MENU
{
POPUP
"&PopUp"
{
MENUITEM "&Say Hello",IDM_HELLO
MENUITEM "Say &GoodBye", IDM_GOODBYE
MENUITEM SEPARATOR
MENUITEM "E&xit",IDM_EXIT
}
MENUITEM
"&Test", IDM_TEST
}
FirstMenu MENU
Declare your menu with MENU keyword.
POPUP
"&PopUp"
{
MENUITEM "&Say Hello",IDM_HELLO
MENUITEM "Say &GoodBye", IDM_GOODBYE
MENUITEM SEPARATOR
MENUITEM "E&xit",IDM_EXIT
}
Define a popup menu with four menu items, the third one is a menu separator.
MENUITEM "&Test", IDM_TEST
Define a
menu bar in the main menu.
Next we will
examine the source code.
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
.IF ax==IDM_TEST
invoke MessageBox,NULL,ADDR Test_string,OFFSET AppName,MB_OK
.ELSEIF ax==IDM_HELLO
invoke MessageBox, NULL,ADDR Hello_string, OFFSET AppName,MB_OK
.ELSEIF ax==IDM_GOODBYE
invoke MessageBox,NULL,ADDR Goodbye_string, OFFSET AppName, MB_OK
.ELSE
invoke DestroyWindow,hWnd
.ENDIF
In the window
procedure, we process WM_COMMAND messages. When the user selects a menu item,
the menu ID of that menu item is sended to the window procedure in the low
word of wParam along with the WM_COMMAND message. So when we store the value
of wParam in eax, we compare the value in ax to the menu IDs we defined previously
and act accordingly. In the first three cases, when the user selects Test,
Say Hello, and Say GoodBye menu items, we just display a text string in a
message box.
If the user
selects Exit menu item, we call DestroyWindow with the handle of our window
as its parameter which will close our window.
As you can
see, specifying menu name in a window class is quite easy and straightforward.
However you can also use an alternate method to load a menu in your window.
I won't show the entire source code here. The resource file is the same in
both methods. There are some minor changes in the source file which I 'll
show below.
invoke LoadMenu, hInst, OFFSET MenuName
mov hMenu,eax
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,hMenu,\
hInst,NULL
Before calling
CreateWindowEx, we call LoadMenu with the instance handle and a pointer to
the name of our menu. LoadMenu returns the handle of our menu in the resource
file which we pass to CreateWindowEx.