📄 tut32.html
字号:
it's active. Choose a safe value such as 100 or above.</font></p>
<p><font face="MS Sans Serif" size="-1">Having filled in the CLIENTCREATESTRUCT
structure, you can create the client window by calling <font color="#000099"><b>CreateWindowEx</b></font>
with the predefined class name,"MDICLIENT", and passing the address
of the CLIENTCREATESTRUCT structure in lParam. You must also specify the handle
to the frame window in the hWndParent parameter so Windows knows the parent-child
relationship between the frame window and the client window. The window styles
you should use are: WS_CHILD ,WS_VISIBLE and WS_CLIPCHILDREN. If you forget
WS_VISIBLE, you won't see the MDI child windows even if they were created successfully.</font></p>
<p><font face="MS Sans Serif" size="-1">The steps in creating the client window
are as follows:</font></p>
<ol>
<li><font face="MS Sans Serif" size="-1">Obtain the handle to the submenu that
you want to append the window list to.</font></li>
<li><font face="MS Sans Serif" size="-1">Put the value of the menu handle along
with the value you want to use as the ID of the first MDI child window in
a CLIENTCREATESTRUCT structure</font></li>
<li><font face="MS Sans Serif" size="-1">call CreateWindowEx with the class
name "MDICLIENT", passing the address of the CLIENTCREATESTRUCT
structure you just filled in in lParam.</font></li>
</ol>
<h3><font face="Tahoma">Creating the MDI Child Window</font></h3>
<p><font face="MS Sans Serif" size="-1">Now you have both the frame window and
the client window. The stage is now ready for the creation of the MDI child
window. There are two ways to do that.</font></p>
<ul>
<li><font face="MS Sans Serif" size="-1">You can send WM_MDICREATE message to<b>
the client window</b>, passing the address of a structure of type MDICREATESTRUCT
in wParam. This is the easiest and the usual method of MDI child window creation.</font>
<blockquote>
<pre><font face="MS Sans Serif" size="-1"><b>.data?<br> mdicreate MDICREATESTRUCT <><br> ....<br>.code<br> .....<br> [fill the members of mdicreate]<br> ......
invoke SendMessage, hwndClient, WM_MDICREATE,addr mdicreate,0</b></font></pre>
</blockquote>
<p><font face="MS Sans Serif" size="-1"><b><font color="#003399">SendMessage</font></b>
will return the handle of the newly created MDI child window if successful.
You don't need to save the handle though. You can obtain it by other means
if you want to. MDICREATESTRUCT has the following definition.</font></p>
</li>
<blockquote> <font face="MS Sans Serif" size="-1"><b>MDICREATESTRUCT STRUCT<br>
szClass DWORD ?<br>
szTitle DWORD ?<br>
hOwner DWORD ?<br>
x DWORD
?<br>
y DWORD
?<br>
lx DWORD
?<br>
ly DWORD
?<br>
style DWORD ?<br>
lParam DWORD ?<br>
MDICREATESTRUCT ENDS</b></font></blockquote>
</ul>
<blockquote>
<table border="1" cellpadding="3">
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">szClass</font></th>
<td><font face="MS Sans Serif" size="-1">the address of the window class
you want to use as the template for the MDI child window.</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">szTitle</font></th>
<td><font face="MS Sans Serif" size="-1">the address of the text you want
to appear in the title bar of the child window</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">hOwner</font></th>
<td><font face="MS Sans Serif" size="-1">the instance handle of the application</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">x,y,lx,ly</font></th>
<td><font face="MS Sans Serif" size="-1">the upper left coordinate and the
width and height of the child window</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">style</font></th>
<td><font face="MS Sans Serif" size="-1">child window style. If you create
the client window with MDIS_ALLCHILDSTYLES, you can use any window style.
</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">lParam</font></th>
<td><font face="MS Sans Serif" size="-1">an application-defined 32-bit value.
This is a way of sharing values among MDI windows. If you don't need to
use it, set it to NULL</font></td>
</tr>
</table>
</blockquote>
<ul>
<li><font face="MS Sans Serif" size="-1">You can call <font color="#003399"><b>CreateMDIWindow</b></font>.
This function has the following syntax:</font> </li>
</ul>
<ul>
<blockquote>
<pre><font face="MS Sans Serif" size="-1"><b>CreateMDIWindow proto lpClassName:DWORD<br> lpWindowName:DWORD<br> dwStyle:DWORD
x:DWORD<br> y:DWORD<br> nWidth:DWORD<br> nHeight:DWORD<br> hWndParent:DWORD<br> hInstance:DWORD<br> lParam:DWORD</b></font></pre>
</blockquote>
</ul>
<blockquote>
<p><font face="MS Sans Serif" size="-1">If you look closely at the parameters,
you'll find that they are identical to the members of MDICREATESTRUCT structure,
except for the <b>hWndParent</b>. Essentially it's the same number of parameters
you pass with WM_MDICREATE. MDICREATESTRUCT doesn't have the <b>hWndParent</b>
field because you must pass the whole structure to the correct client window
with SendMessage anyway.</font></p>
</blockquote>
<p><font face="MS Sans Serif" size="-1">At this point, you may have some questions:
which method should I use? What is the difference between the two? Here is the
answer: </font></p>
<p><font face="MS Sans Serif" size="-1">The WM_MDICREATE method can only create
the MDI child window in the same thread as the calling code. For example, if
your application has 2 threads, and the first thread creates the MDI frame window,
if the second thread wants to create an MDI child, it must do so with CreateMDIChild:
sending WM_MDICREATE message to the first thread won't work. If your application
is single-threaded, you can use either method. (Thanks yap for the correction
- 04/24/2002)</font></p>
<p><font face="MS Sans Serif" size="-1">A little more detail needs to be covered
about the window procedure of the MDI child. As with the frame window case,
you must not call <font color="#000099"><b>DefWindowProc</b></font> to handle
the unprocessed messages. Instead, you must use <font color="#000099"><b>DefMDIChildProc</b></font>.
This function has exactly the same parameters as <font color="#000099"><b>DefWindowProc</b></font>.</font></p>
<p><font face="MS Sans Serif" size="-1">In addition to WM_MDICREATE, there are
other MDI-related window messages. I'll list them below:</font></p>
<table border="1" cellpadding="3" align="center">
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">WM_MDIACTIVATE</font></th>
<td><font face="MS Sans Serif" size="-1">This message can be sent by the application
to the client window to instruct the client window to activate the selected
MDI child. When the client window receives the message, it activates the
selected MDI child window and sends WM_MDIACTIVATE to the child being deactivated
and activated. The use of this message is two-fold: it can be used by the
application to activate the desired child window. And it can be used by
the MDI child window itself as the indicator that it's being activated/deactivated.
For example, if each MDI child window has different menu, it can use this
opportunity to change the menu of the frame window when it's activated/deactivated.</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">WM_MDICASCADE<br>
WM_MDITILE<br>
WM_MDIICONARRANGE </font></th>
<td><font face="MS Sans Serif" size="-1">These messages handle the arrangement
of the MDI child windows. For example, if you want the MDI child windows
to arrange themselves in cascading style, send WM_MDICASCADE to the client
window. </font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">WM_MDIDESTROY</font></th>
<td><font face="MS Sans Serif" size="-1">Send this message to the client window
to destroy an MDI child window. You should use this message instead of calling
<font color="#000099"> <b>DestroyWindow</b></font> because if the MDI child
window is maxmized, this message will restore the tile of the frame window.
If you use <font color="#000099"><b>DestroyWindow</b></font>, the title
of the frame window will not be restored.</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">WM_MDIGETACTIVE</font></th>
<td><font face="MS Sans Serif" size="-1">Send this message to retrieve the
handle of the currently active MDI child window.</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">WM_MDIMAXIMIZE<br>
WM_MDIRESTORE </font></th>
<td><font face="MS Sans Serif" size="-1">Send WM_MDIMAXIMIZE to maximize the
MDI child window and WM_MDIRESTORE to restore it to previous state. Always
use these messages for the operations. If you use ShowWindow with SW_MAXIMIZE,
the MDI child window will maximize fine but it will have the problem when
you try to restore it to previous size. You can minimize the MDI child window
with ShowWindow without problem, however.</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">WM_MDINEXT</font></th>
<td><font face="MS Sans Serif" size="-1">Send this message to the client window
to activate the next or the previous MDI child window according to the values
in wParam and lParam.</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">WM_MDIREFRESHMENU</font></th>
<td><font face="MS Sans Serif" size="-1">Send this message to the client window
to refresh the menu of the frame window. Note that you must call <font color="#000099">
<b>DrawMenuBar</b></font> to update the menu bar after sending this message.</font></td>
</tr>
<tr>
<th nowrap><font face="MS Sans Serif" size="-1">WM_MDISETMENU</font></th>
<td><font face="MS Sans Serif" size="-1">Send this message to the client window
to replace the whole menu of the frame window or just the window submenu.
You must use this message instead of <font color="#000099"><b>SetMenu</b></font>.
After sending this message, you must call <font color="#000099"><b>DrawMenuBar</b></font>
to update the menu bar. Normally you will use this message when the active
MDI child window has its own menu and you want it to replace the menu of
the frame window while the MDI child window is active.</font></td>
</tr>
</table>
<p><font face="MS Sans Serif" size="-1">I'll review the steps in creating an MDI
application for you again below.</font></p>
<ol>
<li><font face="MS Sans Serif" size="-1">Register the window classes, both the
frame window class and the MDI child window class</font></li>
<li><font face="MS Sans Serif" size="-1">Create the frame window with <font color="#000099"><b>CreateWindowEx</b></font>.</font></li>
<li><font face="MS Sans Serif" size="-1">Within the message loop, call <font color="#003399"><b>TranslateMDISysAccel</b></font>
to process the MDI-related accelerator keys</font></li>
<li><font face="MS Sans Serif" size="-1">Within the window procedure of the
frame window, call <font color="#000099"><b>DefFrameProc</b></font> to handle
<b>ALL</b> messages unhandled by your code.</font></li>
<li><font face="MS Sans Serif" size="-1">Create the client window by calling
<font color="#000099"> <b>CreateWindowEx</b></font> using the name of the
predefined window class, "MDICLIENT", passing the address of a CLIENTCREATESTRUCT
structure in lParam. Normally, you would create the client window within the
WM_CREATE handler of the frame window proc</font></li>
<li><font face="MS Sans Serif" size="-1">You can create an MDI child window
by sending WM_MDICREATE to the client window or, alternatively, by calling
<font color="#000099"> <b>CreateMDIWindow</b></font>. </font></li>
<li><font face="MS Sans Serif" size="-1">Within the window proc of the MDI child
window, pass all unhandled messages to <font color="#003366"><b>DefMDIChildProc</b></font>.</font></li>
<li><font face="MS Sans Serif" size="-1">Use MDI version of the messages if
it exists. For example, use WM_MDIDESTROY instead of calling <font color="#003366"><b>DestroyWindow</b></font></font></li>
</ol>
<h3><font face="MS Sans Serif" size="-1">Example:</font></h3>
<pre>.386 <br>.model flat,stdcall <br>option casemap:none <br>include \masm32\include\windows.inc <br>include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
.const
IDR_MAINMENU equ 101
IDR_CHILDMENU equ 102
IDM_EXIT equ 40001
IDM_TILEHORZ equ 40002
IDM_TILEVERT equ 40003
IDM_CASCADE equ 40004
IDM_NEW equ 40005
IDM_CLOSE equ 40006
.data
ClassName db "MDIASMClass",0
MDIClientName db "MDICLIENT",0
MDIChildClassName db "Win32asmMDIChild",0
MDIChildTitle db "MDI Child",0
AppName db "Win32asm MDI Demo",0
ClosePromptMessage db "Are you sure you want to close this window?",0
.data?
hInstance dd ?
hMainMenu dd ?
hwndClient dd ?
hChildMenu dd ?
mdicreate MDICREATESTRUCT <>
hwndFrame dd ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke WinMain, hInstance,NULL,NULL, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
;=============================================
; Register the frame window class
;=============================================
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,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_APPWORKSPACE
mov wc.lpszMenuName,IDR_MAINMENU
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -