WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke IsDialogMessage, hDlg, ADDR msg
.IF eax ==FALSE
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDIF
.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 lParam==0
.IF ax==IDM_GETTEXT
invoke GetDlgItemText,hWnd,IDC_EDIT,ADDR buffer,512
invoke MessageBox,NULL,ADDR buffer,ADDR AppName,MB_OK
.ELSEIF ax==IDM_CLEAR
invoke SetDlgItemText,hWnd,IDC_EDIT,NULL
.ELSE
invoke DestroyWindow,hWnd
.ENDIF
.ELSE
mov edx,wParam
shr edx,16
.IF dx==BN_CLICKED
.IF ax==IDC_BUTTON
invoke SetDlgItemText,hWnd,IDC_EDIT,ADDR TestString
.ELSEIF ax==IDC_EXIT
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.ENDIF
.ENDIF
.ENDIF
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start
------------------------------------------------------------------------
Dialog.rc
------------------------------------------------------------------------
#include "resource.h"
#define IDC_EDIT 3000
#define IDC_BUTTON 3001
#define IDC_EXIT 3002
#define IDM_GETTEXT 32000
#define IDM_CLEAR 32001
#define IDM_EXIT 32003
MyDialog DIALOG 10, 10, 205, 60
STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "Our First Dialog Box"
CLASS "DLGCLASS"
BEGIN
EDITTEXT IDC_EDIT, 15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
DEFPUSHBUTTON "Say Hello", IDC_BUTTON, 141,10,52,13
PUSHBUTTON "E&xit", IDC_EXIT, 141,26,52,13, WS_GROUP
END
MyMenu MENU
BEGIN
POPUP "Test Controls"
BEGIN
MENUITEM "Get Text", IDM_GETTEXT
MENUITEM "Clear Text", IDM_CLEAR
MENUITEM "", , 0x0800 /*MFT_SEPARATOR*/
MENUITEM "E&xit", IDM_EXIT
END
END
Analysis
--------
Let's analyze this first example.
This example shows how to register a dialog template as a window class and
create a "window" from that class. It simplifies your program since you
don't have to create the child window controls yourself.
Let's first analyze the dialog template.
MyDialog DIALOG 10, 10, 205, 60
Declare the name of a dialog, in this case, "MyDialog" followed by the
keyword "DIALOG". The following four numbers are: x, y , width, and height
of the dialog box in dialog box units (not the same as pixels).
STYLE 0x0004 | DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
Declare the styles of the dialog box.
CAPTION "Our First Dialog Box"
This is the text that will appear in the dialog box's title bar.
CLASS "DLGCLASS"
This line is crucial. It's this CLASS keyword that allows us to use the
dialog box template as a window class. Following the keyword is the name of
the "window class"
BEGIN
EDITTEXT IDC_EDIT, 15,17,111,13, ES_AUTOHSCROLL | ES_LEFT
DEFPUSHBUTTON "Say Hello", IDC_BUTTON, 141,10,52,13
PUSHBUTTON "E&xit", IDC_EXIT, 141,26,52,13
END
The above block defines the child window controls in the dialog box.
They're defined between BEGIN and END keywords. Generally the syntax is as
follows:
control-type "text" ,controlID, x, y, width, height [,styles]
control-types are resource compiler's constants so you have to consult the
manual.
Now we go to the assembly source code. The interesting part is in the
window class structure:
mov wc.cbWndExtra,DLGWINDOWEXTRA
mov wc.lpszClassName,OFFSET ClassName
Normally, this member is left NULL, but if we want to register a dialog box
template as a window class, we must set this member to the value
DLGWINDOWEXTRA. Note that the name of the class must be identical to the
one following the CLASS keyword in the dialog box template. The remaining
members are initialized as usual. After you fill the window class
structure, register it with RegisterClassEx. Seems familiar? This is the
same routine you have to do in order to register a normal window class.
invoke CreateDialogParam,hInstance,ADDR DlgName,NULL,NULL,NULL
After registering the "window class", we create our dialog box. In this
example, I create it as a modeless dialog box with CreateDialogParam
function. This function takes 5 parameters but you only have to fill in the
first two: the instance handle and the pointer to the name of the dialog
box template. Note that the 2nd parameter is not a pointer to the class
name.
At this point, the dialog box and its child window controls are created by
Windows. Your window procedure will receive WM_CREATE message as usual.
invoke GetDlgItem,hDlg,IDC_EDIT
invoke SetFocus,eax
After the dialog box is created, I want to set the input focus to the edit
control. If I put these codes in WM_CREATE section, GetDlgItem call will
fail since at that time, the child window controls are not created yet. The
only way you can do this is to call it after the dialog box and all its
child window controls are created. So I put these two lines after the
UpdateWindow call. GetDlgItem function gets the control ID and returns the
associated control's window handle. This is how you can get a window handle
if you know its control ID.
invoke IsDialogMessage, hDlg, ADDR msg
.IF eax ==FALSE
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDIF
The program enters the message loop and before we translate and dispatch
messages, we call IsDialogMessage function to let the dialog box manager
handles the keyboard logic of our dialog box for us. If this function
returns TRUE , it means the message is intended for the dialog box and is
processed by the dialog box manager. Note another difference from the
previous tutorial. When the window procedure wants to get the text from the
edit control, it calls GetDlgItemText function instead of GetWindowText.
GetDlgItemText accepts a control ID instead of a window handle. That makes
the call easier in the case you use a dialog box.
------------------------------------------------------------------------
Now let's go to the second approach to using a dialog box as a main window.
In the next example, I 'll create an application modal dialog box. You'll
not find a message loop or a window procedure because they're not
necessary!
------------------------------------------------------------------------
dialog.asm (part 2)
------------------------------------------------------------------------
.386
.model flat,stdcall
option casemap:none
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
include \masm32\include\windows.inc
include \masm32\include\user32.inc