[ButtonClassName:
'button' 0 ButtonText: 'My First Button' 0
EditClassName:
'edit' 0 TestString: "Wow! I'm
in an edit box now" 0]
[MenuHandle:
0 WindowHandle: 0]
______________________________________________________________________________________
; Window Class Structure:
[WindowClassEx:
wc_Size: len
wc_style: &CS_HREDRAW+&CS_VREDRAW
WndProc: MainWindowProc
wc_ClsExtra: 0 wc_WndExtra: 0
hInstance: 0 wc_hIcon: 0
wc_hCursor: 0 wc_hbrBackground: 16 wc_MenuName: 0
wc_ClassName: ClassName
wc_hIconSm: 0]
[FirstMessage: 0 #7]
[IDM_Menu
1000
IDM_Test_Controls 1001
IDM_Say_Hello 1002
IDM_Clear_Edit_Box
1003 IDM_Get_Text 1004
IDM_Exit 1005]
____________________________________________________________________________________________
____________________________________________________________________________________________
Main:
call 'Kernel32.GetModuleHandleA' &NULL | mov D§hInstance
eax
call 'User32.LoadIconA' 0 &IDI_WINLOGO | mov D§wc_hIcon
eax D§wc_hIconSm eax
call 'User32.LoadCursorA' 0 &IDC_ARROW | mov D§wc_hCursor
eax
call 'User32.RegisterClassExA' WindowClassEX
call 'User32.LoadMenuA' D§hInstance IDM_Menu | mov D§MenuHandle
eax
call 'User32.CreateWindowExA' &WS_EX_CLIENTEDGE ClassName AppName,
&WS_OVERLAPPEDWINDOW,
&CW_USEDEFAULT &CW_USEDEFAULT 300 200,
&NULL D§MenuHandle D§hInstance &NULL
mov D§WindowHandle eax
call 'User32.ShowWindow' D§WindowHandle &SW_SHOWNORMAL
call 'User32.UpdateWindow' D§WindowHandle
L1:
call 'User32.GetMessageA' FirstMessage 0 0 0 | cmp eax 0 | je L9>
call 'User32.TranslateMessage' FirstMessage
call 'User32.DispatchMessageA' FirstMessage
jmp L1<
L9: call 'Kernel32.ExitProcess' 0
__________________________________________________________________________________
[hwndEdit: 0 hwndButton: 0]
[buffer: B§ 0 #512]
[EditID 2 ButtonID 1]
Proc
MainWindowProc:
Arguments @Adressee, @Message, @wParam, @lParam
pushad
...If D@Message = &WM_DESTROY
call 'User32.PostQuitMessage' &NULL
...Else_If D@Message = &WM_CREATE
call 'User32.CreateWindowExA' &WS_EX_CLIENTEDGE EditClassName
&NULL,
&WS_CHILD+&WS_VISIBLE+&WS_BORDER+&ES_LEFT+&ES_AUTOHSCROLL,
50 35 200 25 D@Adressee EditID D§hInstance &NULL
mov D§hwndEdit eax
call 'User32.SetFocus' eax
call 'User32.CreateWindowExA' &NULL ButtonClassName ButtonText,
&WS_CHILD+&WS_VISIBLE+&BS_DEFPUSHBUTTON,
75 70 140 25 D@Adressee ButtonID D§hInstance &NULL
mov D§hwndButton eax
...Else_If D@Message = &WM_COMMAND
mov eax D@wParam
..If D@lParam = 0
.If eax = IDM_Say_Hello
call 'User32.SetWindowTextA' D§hwndEdit TestString
call 'User32.SendMessageA' D§hwndEdit &WM_KEYDOWN &VK_END
&NULL
.Else_If eax = IDM_Clear_Edit_Box
call 'User32.SetWindowTextA' D§hwndEdit &NULL
.Else_If eax = IDM_Get_Text
call 'User32.GetWindowTextA' D§hwndEdit buffer 512
call 'User32.MessageBoxA' &NULL buffer AppName &MB_OK
.Else
call 'User32.DestroyWindow' D@Adressee
.End_If
..Else
.IF eax = ButtonID
shr eax 16
IF eax = &BN_CLICKED
call 'User32.SendMessageA' D@Adressee &WM_COMMAND IDM_Get_Text 0
End_If
.End_If
..End_If
...Else
popad
call 'User32.DefWindowProcA' D@Adressee D@Message D@wParam D@lParam
Exit
...End_If
popad | mov eax &FALSE
EndP
...Else_If D@Message = &WM_COMMAND
mov eax D@wParam
..If D@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 eax = IDM_Say_Hello
call 'User32.SetWindowTextA' D§hwndEdit TestString
call 'User32.SendMessageA' D§hwndEdit &WM_KEYDOWN &VK_END
&NULL
.Else_If eax = IDM_Clear_Edit_Box
call 'User32.SetWindowTextA' D§hwndEdit &NULL
.Else_If eax = IDM_Get_Text
call 'User32.GetWindowTextA' D§hwndEdit buffer 512
call 'User32.MessageBoxA' &NULL buffer 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 eax = ButtonID
shr eax 16
IF eax = &BN_CLICKED
call 'User32.SendMessageA' D@Adressee &WM_COMMAND IDM_Get_Text 0
End_If
.End_If
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.