?? lion-tutorial10.htm
字號:
<html>
<head>
<link rel="stylesheet" href="../../asm.css">
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>
<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<p align="center">Tutorial 10: Dialog Box as Main Window</p>
<hr size="1">
Now comes the really interesting part about GUI, the dialog box. In this tutorial
(and the next), we will learn how to use a dialog box as our main window.
<p>Download the first example <a href="files/tut10-1.zip">here</a>, the second
example <a href="files/tut10-2.zip">here</a>.
<h3> Theory:</h3>
If you play with the examples in the previous tutorial long enough, you 'll find
out that you cannot change input focus from one child window control to another
with Tab key. The only way you can do that is by clicking the control you want
it to gain input focus. This situation is rather cumbersome. Another thing you
might notice is that I changed the background color of the parent window to gray
instead of normal white as in previous examples. This is done so that the color
of the child window controls can blend seamlessly with the color of the client
area of the parent window. There is a way to get around this problem but it's
not easy. You have to subclass all child window controls in your parent window.
<br>
The reason why such inconvenience exists is that child window controls are originally
designed to work with a dialog box, not a normal window. The default color of
child window controls such as a button is gray because the client area of a dialog
box is normally gray so they blend into each other without any sweat on the programmer's
part. <br>
Before we get deep into the detail, we should know first what a dialog box is.
A dialog box is nothing more than a normal window which is designed to work with
child window controls. Windows also provides internal "dialog box manager" which
is responsible for most of the keyboard logic such as shifting input focus when
the user presses Tab, pressing the default pushbutton if Enter key is pressed,
etc so programmers can deal with higher level tasks. Dialog boxes are primarily
used as input/output devices. As such a dialog box can be considered as an input/output
"black box" meaning that you don't have to know how a dialog box works internally
in order to be able to use it, you only have to know how to interact with it.
That's a principle of object oriented programming (OOP) called information hiding.
If the black box is *perfectly* designed, the user can make use of it without
any knowledge on how it operates. The catch is that the black box must be perfect,
that's hard to achieve in the real world. Win32 API is also designed as a black
box too. <br>
Well, it seems we stray from our path. Let's get back to our subject. Dialog boxes
are designed to reduce workload of a programmer. Normally if you put child window
controls on a normal window, you have to subclass them and write keyboard logic
yourself. But if you put them on a dialog box, it will handle the logic for you.
You only have to know how to get the user input from the dialog box or how to
send commands to it. <br>
A dialog box is defined as a resource much the same way as a menu. You write a
dialog box template describing the characteristics of the dialog box and its controls
and then compile the resource script with a resource editor. <br>
Note that all resources are put together in the same resource script file. You
can use any text editor to write a dialog box template but I don't recommend it.
You should use a resource editor to do the job visually since arranging child
window controls on a dialog box is hard to do manually. Several excellent resource
editors are available. Most of the major compiler suites include their own resource
editors. You can use them to create a resource script for your program and then
cut out irrelevant lines such as those related to MFC. <br>
There are two main types of dialog box: modal and modeless. A modeless dialog
box lets you change input focus to other window. The example is the Find dialog
of MS Word. There are two subtypes of modal dialog box: application modal and
system modal. An application modal dialog box doesn't let you change input focus
to other window in the same application but you can change the input focus to
the window of <b>OTHER</b> application. A system modal dialog box doesn't allow
you to change input focus to any other window until you respond to it first. <br>
A modeless dialog box is created by calling CreateDialogParam API function. A
modal dialog box is created by calling DialogBoxParam. The only distinction between
an application modal dialog box and a system modal one is the DS_SYSMODAL style.
If you include DS_SYSMODAL style in a dialog box template, that dialog box will
be a system modal one. <br>
You can communicate with any child window control on a dialog box by using SendDlgItemMessage
function. Its syntax is like this: <br>
<blockquote><b>SendDlgItemMessage proto hwndDlg:DWORD,\</b> <br>
<b>
idControl:DWORD,\</b> <br>
<b>
uMsg:DWORD,\</b> <br>
<b>
wParam:DWORD,\</b> <br>
<b>
lParam:DWORD</b></blockquote>
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:
<blockquote><b>call SendDlgItemMessage, hDlg, ID_EDITBOX, WM_GETTEXT, 256, ADDR
text_buffer</b></blockquote>
In order to know which message to send, you should consult your Win32 API reference.
<br>
Windows also provides several control-specific API functions to get and set data
quickly, for example, GetDlgItemText, CheckDlgButton etc. These control-specific
functions are provided for programmer's convenience so he doesn't have to look
up the meanings of wParam and lParam for each message. Normally, you should use
control-specific API calls when they're available since they make source code
maintenance easier. Resort to SendDlgItemMessage only if no control-specific API
calls are available. <br>
The Windows dialog box manager sends some messages to a specialized callback function
called a dialog box procedure which has the following format:
<blockquote><b>DlgProc proto hDlg:DWORD ,\</b> <br>
<b>
iMsg:DWORD ,\</b> <br>
<b>
wParam:DWORD ,\</b> <br>
<b>
lParam:DWORD</b></blockquote>
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 <b>IS</b> 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
<b>MUST</b> 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.
<br>
There are two distinct uses of a dialog box. You can use it as the main window
of your application or use it as an input device. We 'll examine the first approach
in this tutorial. <br>
"Using a dialog box as main window" can be interpreted in two different senses.
<ol>
<li> You can use the dialog box template as a class template which you register
with RegisterClassEx call. In this case, the dialog box behaves like a "normal"
window: it receives messages via a window procedure referred to by lpfnWndProc
member of the window class, not via a dialog box procedure. The benefit of
this approach is that you don't have to create child window controls yourself,
Windows creates them for you when the dialog box is created. Also Windows
handles the keyboard logic for you such as Tab order etc. Plus you can specify
the cursor and icon of your window in the window class structure.</li>
<br>
Your program just creates the dialog box without creating any parent window.
This approach makes a message loop unnecessary since the messages are sent directly
to the dialog box procedure. You don't even have to register a window class!
</ol>
This tutorial is going to be a long one. I'll present the first approach followed
by the second.
<h3> Examples:</h3>
<hr width="100%">
<center>
<b>dialog.asm</b>
</center>
<hr width="100%">
<br>
<b>.386</b> <br>
<b>.model flat,stdcall</b> <br>
<b>option casemap:none</b> <br>
<b>WinMain proto :DWORD,:DWORD,:DWORD,:DWORD</b> <br>
<b>include \masm32\include\windows.inc</b> <br>
<b>include \masm32\include\user32.inc</b> <br>
<b>include \masm32\include\kernel32.inc</b> <br>
<b>includelib \masm32\lib\user32.lib</b> <br>
<b>includelib \masm32\lib\kernel32.lib</b>
<p><b>.data</b> <br>
<b>ClassName db "DLGCLASS",0</b> <br>
<b>MenuName db "MyMenu",0</b> <br>
<b>DlgName db "MyDialog",0</b> <br>
<b>AppName db "Our First Dialog Box",0</b> <br>
<b>TestString db "Wow! I'm in an edit box now",0</b>
<p><b>.data?</b> <br>
<b>hInstance HINSTANCE ?</b> <br>
<b>CommandLine LPSTR ?</b> <br>
<b>buffer db 512 dup(?)</b>
<p><b>.const</b> <br>
<b>IDC_EDIT equ 3000</b> <br>
<b>IDC_BUTTON equ 3001</b> <br>
<b>IDC_EXIT equ 3002</b> <br>
<b>IDM_GETTEXT equ 32000</b> <br>
<b>IDM_CLEAR equ 32001</b> <br>
<b>IDM_EXIT equ 32002</b>
<p><b>.code</b> <br>
<b>start:</b> <br>
<b> invoke GetModuleHandle, NULL</b> <br>
<b> mov hInstance,eax</b> <br>
<b> invoke GetCommandLine<br>
mov CommandLine,eax</b> <br>
<b> invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT</b>
<br>
<b> invoke ExitProcess,eax</b>
<p><b>WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD</b>
<br>
<b> LOCAL wc:WNDCLASSEX</b> <br>
<b> LOCAL msg:MSG</b> <br>
<b> LOCAL hDlg:HWND</b> <br>
<b> mov wc.cbSize,SIZEOF WNDCLASSEX</b> <br>
<b> mov wc.style, CS_HREDRAW or CS_VREDRAW</b>
<br>
<b> mov wc.lpfnWndProc, OFFSET WndProc</b> <br>
<b> mov wc.cbClsExtra,NULL</b> <br>
<b> mov wc.cbWndExtra,DLGWINDOWEXTRA</b> <br>
<b> push hInst</b> <br>
<b> pop wc.hInstance</b> <br>
<b> mov wc.hbrBackground,COLOR_BTNFACE+1</b> <br>
<b> mov wc.lpszMenuName,OFFSET MenuName</b> <br>
<b> mov wc.lpszClassName,OFFSET ClassName</b>
<br>
<b> invoke LoadIcon,NULL,IDI_APPLICATION</b> <br>
<b> mov wc.hIcon,eax</b> <br>
<b> mov wc.hIconSm,eax</b> <br>
<b> invoke LoadCursor,NULL,IDC_ARROW</b> <br>
<b> mov wc.hCursor,eax</b> <br>
<b> invoke RegisterClassEx, addr wc</b> <br>
<b> invoke CreateDialogParam,hInstance,ADDR DlgName,NULL,NULL,NULL</b>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -