The tenth lesson is the application of the main interface with the dialog.
Now we start learning some interesting parts about GUI programming, namely: Applications for the dialog as the main interface. We will tell this process in two lessons.
Theory: If you carefully pay attention to the previous program, you will find: You can't press the Tab button to jump from a sub-window control to another, if you want to transfer, you only use the mouse to click. This is unfriendled for users. Another thing is if you change the background color of the main window from white as a gray like the previous lesson, you must fine classify all sub-windows for the child window control. The reason why the above inconvenience is that the sub-window control is designed to dialog, the background color of the icon window control is gray, and the background color of the dialog is also gray, so that they have coordinated each other, without having to Programmers join other processes. We must know what dialog box before we deeply discuss dialog box. A dialog is actually a window with a lot of sub-window controls, and Windows has a manager inside the dialog, which is processed by pressing the Tab key, and entering the focus from a sub-window space to another Sub-window control. Pressing the Enter or equal to the mouse and so on, so that the programmer can concentrate on their logic. The dialog is mainly used as an input and output interface, and people do not need to know how they internal work, and as long as you know how to interact with them. This is also a so-called information hidden in object-oriented design. As long as the implementation in this black box is perfect, we can use it with confidence, of course, we must emphasize that "black box" must be perfect. The implementation of the Win32 API is a "black box". Oh, it seems that we will discuss some of the questions. Now let's go back to the topic, the design of the dialog is to reduce the workload of the programmer, and if you put a sub-window control yourself in the window You must handle it yourself The key logic and fine classification of its window procedure. If you put it in the dialog box, these shortals dialogs will handle themselves. You just know how to get the user entered data and how to put the data into the sub-window control. Dialog boxes and menus are defined as a resource as in the program, you can write a dialog template in the script file, which contain the feature of the dialog and sub-window, and then edit with the resource editor. It should be noted that all resources must be placed in the same script file. Although the script file can be edited with a text editor, it is best to use some visualized edits when it is necessary to adjust some coordinate values when adjusting the position of the sub-window control, so that it is more convenient. Generally speaking in the compiler's development kit, you can use them to generate a template and then delete some sub-window controls. There are two main dialogs: Mode dialogs and non-Mode dialogs. The Mode dialog allows you to switch the input focus to another window, and the dialog does not need to be closed. For example, the Find dialog in MS Word. There are two types of mode dialogs: Application Mode dialogs and system dialogs. The Application dialog box does not allow you toggle the input focus in this application, but you can switch to other applications, and the system dialog box must be a response to the dialog, otherwise you cannot switch to any application go with. To create a non-Mode dialog, call the API function createDialogParam, and create a mode dialog box call API function DialogBoxParam. The difference between the application mode dialog and the system mode dialog is different. To create a system mode dialog box must "or" on the DS_SYSMODAL flag. In the dialog box, if you want to communicate with the sub-window control, call the function SenddlgItemMESAGE. The syntax of this function is as follows:
Senddlgitemmessage Proto Hwnddlg: DWORD, /
IDControl: DWORD, /
UMSG: DWORD, /
WPARAM: DWORD, /
LParam: DWORD
This PAI function is very useful for sending aspects to sub-window controls. For example, if you want to get a string in the editor control, you can do this: Call senddlgitemmessage, hdlg, id_editbox, wm_gettext, 256, addr text_buffer
Specifically to send those messages should query the relevant Win32 API reference manual. Windows also provides a function of several quick access control data. Such as: getDlgitemtext, checkdlgbutton, etc. In this way, you can get relevant information without querying the WPARAM and LPARAM parameters of each message. You should use these API functions as much as possible so that your code is easier to maintain. The management function of the dialog box will send some messages to a specific callback function: dialog process processing function, the format of this function is:
DLGPROC Proto HDLG: DWORD, /
IMSG: DWORD, /
WPARAM: DWORD, /
LParam: DWORD
The format of this function is very similar to the window process function, except that the return value is Ture and false instead of HRESULT, the dialog manager stored inside Windows is the true window process function of the dialog. It will pass some messages to our window process function. So when our window process function processes these messages, returns Ttrue, otherwise it returns false in EAX. This also means that our window process function does not call the DEFWINDOWPROC function when accepted the message you do not process, as it is not a real window process function. There are two usage for the dialog: one is to use it as a main window, one is to use it as an input and output device. In this lesson, we will demonstrate the first usage. "Use the dialog as the main window": 1. You can call the RegisterClassex function to register the dialog template as a window class. This behavior of the dialog is similar to a normal window: it processes all messages by the window procedure specified in the registration window, the advantage of using the dialog in this way is that you do not need to create a sub-window Controls, Windows itself will help you create, and you will also handle all button logic, and you can specify the cursor and icon in your window structure; 2. Your application creates a dialog window without a parent window. In this method, it is not necessary to need a code to process the message loop because all messages are sent directly to the dialog process handler so you can also register a window. class. In this lesson, my door will use the first method and then use the second method.
example:
Dialog.asm
.386
.Model flat, stdcall
Option CaseMAP: NONE
Winmain Proto: DWORD,: DWORD,: DWORD,: DWORD
INCLUDE /MASM32/INCLUDE/Windows.inc
INCLUDE /MASM32/INCLUDE/USER32.INC
INCLUDE /MASM32/INCLUDE / WANEL32.INC
INCLUDELIB /MASM32/LIB/USER32.LIB
INCLUDELIB /MASM32/LIB/kernel32.lib
.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 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 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) IN Voke isdialogmessage, hdlg, addr msg .if eax == false Invoke TranslateMessage, Addr Msg Invoke DispatchMessage, Addr Msg .ndif.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 EA X, EAX RET WNDPROC ENDP End StartDialog.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 ENDMyMenu MENU BEGIN POPUP "Test Controls" BEGIN MENUITEM "Get Text", IDM_GETTEXT MENUITEM " Clear text ", idm_clear meneuitem", 0x0800 / * mft_separator * / menuitem "e & xit", IDM_EXIT End end
Analysis: Let's analyze the first example:
This example shows how to register a dialog template into a window class and create a window derived by the window class. Since you don't have to create a sub-window control yourself, you simplify a lot of work.
Let's first analyze dialog templates.
MYDIALOG DIALOG 10, 10, 205, 60
First, the name of the dialog is the keyword "dailog". In the next four numbers, the first two is the coordinates of the dialog, the latter two is the width and high of the dialog (note: their units are the unit of the dialog, not necessarily a pixel point).
Style 0x0004 | DS_Center | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
The style of the dialog is defined above.
Caption "Our First Dialog Box"
This is a title displayed on the dialog title bar.
Class "DLGCLASS"
This line is very important. It is there is a keyword class, we can use it to declare a dialog as a window. The name of the "window class" following the keyword.
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
One of the above defines sub-window controls in the dialog box, which is declared between two keywords Begin and End of one end.
Control-Type "Text", ControlID, X, Y, Width, Height [, Styles]
The type of control is the resource editor defines a constant, you can find the relevant manual.
Now let's take a look at the source code. See this part first:
Mov wc.cbwndextra, dlgwindowextramov wc.lpszclassname, Offset ClassName
Usually CBWndextra is set to null, but we want to register a dialog template into a window class, we must set the value of the member to DLGWindowextra. Note that the name of the class must be the same as the name behind the Class key. The remaining member variables and the declaration of the general window class. Fill in the window structure variable after calling the function registerclassex to register. It seems that all this is the same as if you register a normal window.
Invoke CreateDialogparam, Hinstance, Addr Dlgname, Null, Null, NULL
After registration, we create this dialog. In this example, we call the function createDialogParam to generate a non-Mode dialog. This function has a total of 5 parameters, where the first two parameters are required: unique handles and pointers to the dialog template name. Note that the second parameter is a pointer to the template name instead of the class name. At this time, Windows will generate a dialog box and a sub-control window. At the same time your application will receive the first message WM_CREATE transmitted by Windows.
Invoke getdlgitem, hdlg, idc_edit
Invoke setfocus, EAX
After the dialog is generated, we set the input and output focus on the editing control. If the code is set in the WM_CREATE message processing segment, the getDLGITEM function will fail because the space window has not generated, and the function is called after the dialog and all sub-window controls. We arrange the function. After UpdatWindow, the getDLGITEM function returns the open handle of the control.
Invoke isdialogmessage, HDLG, Addr Msg .if Eax == false Invoke TranslateMessage, Addr Msg Invoke DispatchMessage, Addr Msg .endif
The program is now entering the message loop. Before we translate and distribute the message, the function causes the dialog management program built into the dialog to handle the relevant keyboard jump logic. If the function returns True, the indicator message is already handled by the function. Note that the previous lesson is different. When we want to get the text information of the control, call the getDlgiteMtext function and the frontWindowText function, the former accepts the parameter is the ID number of a control, not the handle of the window, which makes call the function in the dialog box. Convenience.
Well, we now use the second method to use a dialog as a main window. In the next example, we will generate an application's mode dialog that you will find that there is no message loop or window processing, because they don't have need!
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 include /masm32/include/kernel32.inc includelib /masm32/lib/user32.lib incrudelib /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 .Ndif.ndif .else Mov Eax, False Ret .ndif Mov Eax, True Ret DLGPROC ENDP End StartDialog.rc (Part 2)
#include "resource.h"
#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 endidr_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
analyse as below:
DLGPROC Proto: DWORD,: DWORD,: DWORD,: DWORD
We have defined the prototype of the DLGProc function, so you can use operator AddR to get its address (remember, it can dynamically obtain the valid address of the identifier at runtime):
Invoke Dialogboxparam, Hinstance, Addr Dlgname, Null, Addr DLGPROC, NULL
The above line calls the function DialogBoxParam, which has five parameters, namely: the unique example handle, the name of the dialog template, the handle of the parent window, the address of the dialog process function, and the data related to the dialog. This function produces a mode dialog. If the function is not displayed, the function is not returned.
.IF uMSG == WM_INITDIALOG INVOKE GETDLGITEM, HWND, IDC_EDIT INVOKE SETFOCUS, EAX .ELSEIF UMSG == WM_Close Invoke SendMsSage, HWnd, WM_COMMAND, IDM_EXIT, 0