Download the example here.
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
ButtonClassName
db "button",0
ButtonText
db "My First Button",0
EditClassName
db "edit",0
TestString
db "Wow! I'm in an edit box now",0
.data?
hInstance
HINSTANCE ?
CommandLine
LPSTR ?
hwndButton
HWND ?
hwndEdit
HWND ?
buffer
db 512 dup(?)                   
; buffer to store the text retrieved from the edit box
.const
ButtonID
equ 1                               
; The control ID of the button control
EditID
equ 2                                   
; The control ID of the edit control
IDM_HELLO
equ 1
IDM_CLEAR
equ 2
IDM_GETTEXT
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_BTNFACE+1
   
mov   wc.lpszMenuName,OFFSET MenuName
   
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,WS_EX_CLIENTEDGE,ADDR ClassName, \
                       
ADDR AppName, WS_OVERLAPPEDWINDOW,\
                       
CW_USEDEFAULT, CW_USEDEFAULT,\
                       
300,200,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 TranslateMessage, ADDR msg
       
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_CREATE
       
invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,\
                       
WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\
                       
ES_AUTOHSCROLL,\
                       
50,35,200,25,hWnd,8,hInstance,NULL
       
mov  hwndEdit,eax
       
invoke SetFocus, hwndEdit
       
invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonText,\
                       
WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,\
                       
75,70,140,25,hWnd,ButtonID,hInstance,NULL
       
mov  hwndButton,eax
   
.ELSEIF uMsg==WM_COMMAND
       
mov eax,wParam
       
.IF lParam==0
           
.IF ax==IDM_HELLO
               
invoke SetWindowText,hwndEdit,ADDR TestString
           
.ELSEIF ax==IDM_CLEAR
               
invoke SetWindowText,hwndEdit,NULL
           
.ELSEIF  ax==IDM_GETTEXT
               
invoke GetWindowText,hwndEdit,ADDR buffer,512
               
invoke MessageBox,NULL,ADDR buffer,ADDR AppName,MB_OK
           
.ELSE
               
invoke DestroyWindow,hWnd
           
.ENDIF
       
.ELSE
           
.IF ax==ButtonID
               
shr eax,16
               
.IF ax==BN_CLICKED
                   
invoke SendMessage,hWnd,WM_COMMAND,IDM_GETTEXT,0
               
.ENDIF
           
.ENDIF
       
.ENDIF
   
.ELSE
       
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
       
ret
   
.ENDIF
    
xor    eax,eax
   
ret
WndProc
endp
end
start
   
.ELSEIF uMsg==WM_COMMAND
       
mov eax,wParam
       
.IF lParam==0
Recall
that a menu also sends WM_COMMAND messages to notify the window about its
state too. How can you differentiate between WM_COMMAND messages originated
from a menu or a control? Below is the answer
 
| Low word of wParam | High word of wParam | lParam | |
| Menu | Menu ID | 0 | 0 | 
| Control | Control ID | Notification code | Child Window Handle | 
You can see that you should check lParam. If it's zero, the current WM_COMMAND message is from a menu. You cannot use wParam to differentiate between a menu and a control since the menu ID and control ID may be identical and the notification code may be zero.
           
.IF ax==IDM_HELLO
               
invoke SetWindowText,hwndEdit,ADDR TestString
           
.ELSEIF ax==IDM_CLEAR
               
invoke SetWindowText,hwndEdit,NULL
           
.ELSEIF  ax==IDM_GETTEXT
               
invoke GetWindowText,hwndEdit,ADDR buffer,512
               
invoke MessageBox,NULL,ADDR buffer,ADDR AppName,MB_OK
You
can put a text string into an edit box by calling SetWindowText. You clear
the content of an edit box by calling SetWindowText with NULL. SetWindowText
is a general purpose API function. You can use SetWindowText to change
the caption of a window or the text on a button.
To
get the text in an edit box, you use GetWindowText.
           
.IF ax==ButtonID
               
shr eax,16
               
.IF ax==BN_CLICKED
                   
invoke SendMessage,hWnd,WM_COMMAND,IDM_GETTEXT,0
               
.ENDIF
           
.ENDIF
The
above code snippet deals with the condition when the user presses the button.
First, it checks the low word of wParam to see if the control ID matches
that of the button. If it is, it checks the high word of wParam to see
if it is the notification code BN_CLICKED which is sent when the button
is clicked.
The
interesting part is after it's certain that the notification code is BN_CLICKED.
We want to get the text from the edit box and display it in a message box.
We can duplicate the code in the IDM_GETTEXT section above but it doesn't
make sense. If we can somehow send a WM_COMMAND message with the low word
of wParam containing the value IDM_GETTEXT to our own window procedure,
we can avoid code duplication and simplify our program. SendMessage function
is the answer. This function sends any message to any window with any wParam
and lParam we want. So instead of duplicating the code, we call SendMessage
with the parent window handle, WM_COMMAND, IDM_GETTEXT, and 0. This has
identical effect to selecting "Get Text" menu item from the menu. The window
procedure doesn't perceive any difference between the two.
You
should use this technique as much as possible to make your code more organized.
Last
but not least, do not forget the TranslateMessage function in the message
loop. Since you must type in some text into the edit box, your program
must translate raw keyboard input into readable text. If you omit this
function, you will not be able to type anything into your edit box.