Download the first example here, the second example here.
SendDlgItemMessage proto hwndDlg:DWORD,\This API call is immensely useful for interacting with a child window control. For example, if you want to get the text from an edit control, you can do this:
idControl:DWORD,\
uMsg:DWORD,\
wParam:DWORD,\
lParam:DWORD
call SendDlgItemMessage, hDlg, ID_EDITBOX, WM_GETTEXT, 256, ADDR text_bufferIn order to know which message to send, you should consult your Win32 API reference.
DlgProc proto hDlg:DWORD ,\The dialog box procedure is very similar to a window procedure except for the type of return value which is TRUE/FALSE instead of LRESULT. The internal dialog box manager inside Windows IS the true window procedure for the dialog box. It calls our dialog box procedure with some messages that it received. So the general rule of thumb is that: if our dialog box procedure processes a message,it MUST return TRUE in eax and if it does not process the message, it must return FALSE in eax. Note that a dialog box procedure doesn't pass the messages it does not process to the DefWindowProc call since it's not a real window procedure.
iMsg:DWORD ,\
wParam:DWORD ,\
lParam:DWORD
.data
ClassName
db "DLGCLASS",0
MenuName
db "MyMenu",0
DlgName
db "MyDialog",0
AppName
db "Our First Dialog Box",0
TestString
db "Wow! I'm in an edit box now",0
.data?
hInstance
HINSTANCE ?
CommandLine
LPSTR ?
buffer
db 512 dup(?)
.const
IDC_EDIT
equ 3000
IDC_BUTTON
equ 3001
IDC_EXIT
equ 3002
IDM_GETTEXT
equ 32000
IDM_CLEAR
equ 32001
IDM_EXIT
equ 32002
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
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 hDlg: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,DLGWINDOWEXTRA
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 CreateDialogParam,hInstance,ADDR DlgName,NULL,NULL,NULL
mov hDlg,eax
invoke ShowWindow, hDlg,SW_SHOWNORMAL
invoke UpdateWindow, hDlg
invoke GetDlgItem,hDlg,IDC_EDIT
invoke SetFocus,eax
.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
#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
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:
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.
DlgProc 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
DlgName
db "MyDialog",0
AppName
db "Our Second Dialog Box",0
TestString
db "Wow! I'm in an edit box now",0
.data?
hInstance
HINSTANCE ?
CommandLine
LPSTR ?
buffer
db 512 dup(?)
.const
IDC_EDIT
equ 3000
IDC_BUTTON
equ 3001
IDC_EXIT
equ 3002
IDM_GETTEXT
equ 32000
IDM_CLEAR
equ 32001
IDM_EXIT
equ 32002
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
invoke ExitProcess,eax
DlgProc
proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_INITDIALOG
invoke GetDlgItem, hWnd,IDC_EDIT
invoke SetFocus,eax
.ELSEIF uMsg==WM_CLOSE
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.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
.ELSEIF ax==IDM_EXIT
invoke EndDialog, hWnd,NULL
.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
mov eax,FALSE
ret
.ENDIF
mov eax,TRUE
ret
DlgProc
endp
end
start
#define
IDC_EDIT
3000
#define
IDC_BUTTON
3001
#define
IDC_EXIT
3002
#define IDR_MENU1 3003
#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 Second Dialog Box"
MENU
IDR_MENU1
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
IDR_MENU1
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
DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD
We declare the function prototype for DlgProc so we can refer to it with addr operator in the line below:
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
The above line calls DialogBoxParam function which takes 5 parameters: the instance handle, the name of the dialog box template, the parent window handle, the address of the dialog box procedure, and the dialog-specific data. DialogBoxParam creates a modal dialog box. It will not return until the dialog box is destroyed.
.IF uMsg==WM_INITDIALOG
invoke GetDlgItem, hWnd,IDC_EDIT
invoke SetFocus,eax
.ELSEIF uMsg==WM_CLOSE
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
The
dialog box procedure looks like a window procedure except that it doesn't
receive WM_CREATE message. The first message it receives is WM_INITDIALOG.
Normally you can put the initialization code here. Note that you must return
the value TRUE in eax if you process the message.
The
internal dialog box manager doesn't send our dialog box procedure the WM_DESTROY
message by default when WM_CLOSE is sent to our dialog box. So if we want
to react when the user presses the close button on our dialog box, we must
process WM_CLOSE message. In our example, we send WM_COMMAND message with
the value IDM_EXIT in wParam. This has the same effect as when the user
selects Exit menu item. EndDialog is called in response to IDM_EXIT.
The
processing of WM_COMMAND messages remains the same.
When
you want to destroy the dialog box, the only way is to call EndDialog function.
Do not try DestroyWindow! EndDialog doesn't destroy the dialog box immediately.
It only sets a flag for the internal dialog box manager and continues to
execute the next instructions.
Now
let's examine the resource file. The notable change is that instead of
using a text string as menu name we use a value, IDR_MENU1. This is necessary
if you want to attach a menu to a dialog box created with DialogBoxParam.
Note that in the dialog box template, you have to add the keyword MENU
followed by the menu resource ID.
A
difference between the two examples in this tutorial that you can readily
observe is the lack of an icon in the latter example. However, you can
set the icon by sending the message WM_SETICON to the dialog box during
WM_INITDIALOG.