Download the first example here, the second example here.
LONG SendDlgItemMessage(This API call is the only one you have to know to be able to send and get messages and data to and from a child window control. For example, if you want to get the text from an edit control, you can do this:HWND hwndDlg, // handle of dialog box
int idControl, // identifier of control
UINT uMsg, // message to send
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
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.
.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(?),0
.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:SDWORD
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 hInstance
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,0
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
mov eax,uMsg
.IF eax==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF eax==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
.IF ax==IDC_BUTTON
shr eax,16
.IF ax==BN_CLICKED
invoke SetDlgItemText,hWnd,IDC_EDIT,ADDR TestString
.ENDIF
.ELSEIF ax==IDC_EXIT
shr eax,16
.IF ax==BN_CLICKED
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.
.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(?),0
.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:SDWORD
mov eax, OFFSET DlgProc
invoke DialogBoxParam,
hInst, ADDR DlgName,NULL, eax,NULL
ret
WinMain endp
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM,
lParam:LPARAM
mov eax,uMsg
.IF eax==WM_INITDIALOG
invoke GetDlgItem, hWnd,IDC_EDIT
invoke SetFocus,eax
.ELSEIF eax==WM_CLOSE
invoke SendMessage,hWnd,WM_COMMAND,IDM_EXIT,0
.ELSEIF eax==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
.IF ax==IDC_BUTTON
shr eax,16
.IF ax==BN_CLICKED
invoke SetDlgItemText,hWnd,IDC_EDIT,ADDR TestString
.ENDIF
.ELSEIF ax==IDC_EXIT
shr eax,16
.IF ax==BN_CLICKED
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
mov eax, OFFSET DlgProc
invoke DialogBoxParam,
hInst, ADDR DlgName,NULL, eax,NULL
ret
In the WinMain function, there are only these three lines of code. The first line stores the offset of the dialog box procedure into eax. The next line is the call to 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 eax==WM_INITDIALOG
invoke GetDlgItem, hWnd,IDC_EDIT
invoke SetFocus,eax
.ELSEIF eax==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. 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.
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!
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.