⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tut32.html

📁 WINDOWS程序员使用指南--汇编基础
💻 HTML
📖 第 1 页 / 共 3 页
字号:
	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 
	;================================================    
	; Register the MDI child window class 
	;================================================    
	mov wc.lpfnWndProc,offset ChildProc 
	mov wc.hbrBackground,COLOR_WINDOW+1 
	mov wc.lpszClassName,offset MDIChildClassName 
	invoke RegisterClassEx,addr wc 
	invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\ 
			WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN,CW_USEDEFAULT,\    
			CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,0,\ 
			hInst,NULL 
	mov hwndFrame,eax    
<font color="#990033">	invoke LoadMenu,hInstance, IDR_CHILDMENU 
	mov hChildMenu,eax </font>
	invoke ShowWindow,hwndFrame,SW_SHOWNORMAL 
	invoke UpdateWindow, hwndFrame 
	.while TRUE 
		invoke GetMessage,ADDR msg,NULL,0,0 
		.break .if (!eax) 
		invoke TranslateMDISysAccel,hwndClient,addr msg 
		.if !eax 
			invoke TranslateMessage, ADDR msg 
			invoke DispatchMessage, ADDR msg 
		.endif 
	.endw 
	invoke DestroyMenu, hChildMenu 
	mov eax,msg.wParam 
	ret 
WinMain endp 

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM 
	LOCAL ClientStruct:CLIENTCREATESTRUCT    
	.if uMsg==WM_CREATE 
		invoke GetMenu,hWnd 
		mov hMainMenu,eax 
		invoke GetSubMenu,hMainMenu,1    
		mov ClientStruct.hWindowMenu,eax 
		mov ClientStruct.idFirstChild,100 
		INVOKE CreateWindowEx,NULL,ADDR MDIClientName,NULL,\ 
				WS_CHILD or WS_VISIBLE or WS_CLIPCHILDREN,CW_USEDEFAULT,\
				CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hWnd,NULL,\ 
				hInstance,addr ClientStruct    
		mov hwndClient,eax 
		;======================================= 
		; Initialize the MDICREATESTRUCT 
		;======================================= 
		mov mdicreate.szClass,offset MDIChildClassName 
		mov mdicreate.szTitle,offset MDIChildTitle 
		push hInstance    
		pop mdicreate.hOwner 
		mov mdicreate.x,CW_USEDEFAULT 
		mov mdicreate.y,CW_USEDEFAULT    
		mov mdicreate.lx,CW_USEDEFAULT 
		mov mdicreate.ly,CW_USEDEFAULT 
	.elseif uMsg==WM_COMMAND    
		.if lParam==0 
			mov eax,wParam 
			.if ax==IDM_EXIT 
				invoke SendMessage,hWnd,WM_CLOSE,0,0    
			.elseif ax==IDM_TILEHORZ 
				invoke SendMessage,hwndClient,WM_MDITILE,MDITILE_HORIZONTAL,0 
			.elseif ax==IDM_TILEVERT 
				invoke SendMessage,hwndClient,WM_MDITILE,MDITILE_VERTICAL,0    
			.elseif ax==IDM_CASCADE 
				invoke SendMessage,hwndClient,WM_MDICASCADE,MDITILE_SKIPDISABLED,0	   
			.elseif ax==IDM_NEW 
				invoke SendMessage,hwndClient,WM_MDICREATE,0,addr mdicreate   
			.elseif ax==IDM_CLOSE 
				invoke SendMessage,hwndClient,WM_MDIGETACTIVE,0,0 
				invoke SendMessage,eax,WM_CLOSE,0,0 
			.else 
				invoke DefFrameProc,hWnd,hwndClient,uMsg,wParam,lParam	   
				ret
			.endif 
		.endif 
	.elseif uMsg==WM_DESTROY 
		invoke PostQuitMessage,NULL 
	.else 
		invoke DefFrameProc,hWnd,hwndClient,uMsg,wParam,lParam 
		ret 
	.endif 
	xor eax,eax 
	ret 
WndProc endp 

ChildProc proc hChild:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD 
	.if uMsg==WM_MDIACTIVATE    
		mov eax,lParam 
		.if eax==hChild 
			invoke GetSubMenu,hChildMenu,1 
			mov edx,eax 
			invoke SendMessage,hwndClient,WM_MDISETMENU,hChildMenu,edx 
		.else 
			invoke GetSubMenu,hMainMenu,1    
			mov edx,eax 
			invoke SendMessage,hwndClient,WM_MDISETMENU,hMainMenu,edx 
		.endif 
		invoke DrawMenuBar,hwndFrame 
	.elseif uMsg==WM_CLOSE   
		invoke MessageBox,hChild,addr ClosePromptMessage,addr AppName,MB_YESNO 
		.if eax==IDYES    
			invoke SendMessage,hwndClient,WM_MDIDESTROY,hChild,0 
		.endif 
	.else 
		invoke DefMDIChildProc,hChild,uMsg,wParam,lParam    
		ret 
	.endif 
	xor eax,eax 
	ret 
ChildProc endp 
end start 
</pre>
<h3><font face="MS Sans Serif" size="-1">Analysis:</font></h3>
<p><font face="MS Sans Serif" size="-1">The first thing the program does is to 
  register the window classes of the frame window and the MDI child window. After 
  that, it calls CreateWindowEx to create the frame window. Within the WM_CREATE 
  handler of the frame window, we create the client window:</font> <br>
</p>
<pre>
	LOCAL ClientStruct:CLIENTCREATESTRUCT 
	.if uMsg==WM_CREATE 
		invoke GetMenu,hWnd    
		mov hMainMenu,eax 
		invoke GetSubMenu,hMainMenu,1 
<font color="#990033"><b>		mov ClientStruct.hWindowMenu,eax    
		mov ClientStruct.idFirstChild,100 </b></font>
		invoke CreateWindowEx,NULL,ADDR MDIClientName,NULL,\    
			WS_CHILD or WS_VISIBLE or WS_CLIPCHILDREN,CW_USEDEFAULT,\ 
			CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hWnd,NULL,\    
			hInstance,<font color="#990033"><b>addr ClientStruct</b></font> 
		mov hwndClient,eax 
</pre>
<p><font face="MS Sans Serif" size="-1">It calls <font color="#000099"><b>GetMenu</b></font> 
  to obtain the handle to the menu of the frame window, to be used in the <font color="#000066"><b>GetSubMenu</b></font> 
  call. Note that we pass the value 1 to <font color="#000099"><b>GetSubMenu</b></font> 
  because the submenu we want the window list to appear is the second submenu. 
  Then we fill the members of the CLIENTCREATESTRUCT structure.</font><br>
  <font face="MS Sans Serif" size="-1">Next, we initialize the MDICLIENTSTRUCT 
  structure. Note that we don't need to do it here. It's only convenient to do 
  it in WM_CREATE.</font></p>
<pre>	mov mdicreate.szClass,offset MDIChildClassName 
	mov mdicreate.szTitle,offset MDIChildTitle 
	push hInstance 
	pop mdicreate.hOwner 
	mov mdicreate.x,CW_USEDEFAULT    
	mov mdicreate.y,CW_USEDEFAULT 
	mov mdicreate.lx,CW_USEDEFAULT 
	mov mdicreate.ly,CW_USEDEFAULT
</pre>
<p><font face="MS Sans Serif" size="-1">After the frame window is created (and 
  also the client window), we call <font color="#000099"><b>LoadMenu</b></font> 
  to load the child window menu from the resource. We need to get this menu handle 
  so we can replace the menu of the frame window with it when an MDI child window 
  is present. Don't forget to call <font color="#000099"><b>DestroyMenu</b></font> 
  on the handle before the application exits to Windows. Normally Windows will 
  free the menu associated with a window automatically when the application exits 
  but in this case, the child window menu is not associated with any window thus 
  it will still occupy valuable memory even after the application exits.</font><br>
</p>
<pre>	invoke LoadMenu,hInstance, IDR_CHILDMENU 
	mov hChildMenu,eax 
	........
	invoke DestroyMenu, hChildMenu
</pre>
<p><font face="MS Sans Serif" size="-1">Within the message loop, we call <font color="#000099"><b>TranslateMDISysAccel</b></font>.</font></p>
<pre>	.while TRUE 
		invoke GetMessage,ADDR msg,NULL,0,0 
		.break .if (!eax) 
		<font color="#990066"><b>invoke TranslateMDISysAccel,hwndClient,addr msg</b></font> 
		.if !eax 
			invoke TranslateMessage, ADDR msg 
			invoke DispatchMessage, ADDR msg 
		.endif 
	.endw </pre>
<p><font face="MS Sans Serif" size="-1">If <font color="#000099"><b>TranslateMDISysAccel</b></font> 
  returns a non-zero value, it means the message was already handled by Windows 
  itself so you don't need to do anything to the message. If it returns 0, the 
  message is not MDI-related and thus should be handled as usual.</font><br>
</p>
<pre>WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM 
	.....
	.else 
<font color="#990033"><b>		invoke DefFrameProc,hWnd,hwndClient,uMsg,wParam,lParam 
		ret </b></font>
	.endif
	xor eax,eax
	ret
WndProc endp</pre>
<p><font face="MS Sans Serif" size="-1">Note that within the window procedure 
  of the frame window, we call DefFrameProc to handle the messages we are not 
  interested in.</font></p>
<p><font face="MS Sans Serif" size="-1">The bulk of the window procedure is the 
  WM_COMMAND handler. When the user selects &quot;New&quot; from the File menu, 
  we create a new MDI child window.</font></p>
<pre>	.elseif ax==IDM_NEW 
		invoke SendMessage,hwndClient,WM_MDICREATE,0,addr mdicreate
</pre>
<p><font face="MS Sans Serif" size="-1">In our example, we create the MDI child 
  window by sending WM_MDICREATE to the client window, passing the address of 
  the MDICREATESTRUCT structure in lParam.</font></p>
<pre>ChildProc proc hChild:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD 
	.if uMsg==WM_MDIACTIVATE    
		mov eax,lParam 
		.if eax==hChild 
			invoke GetSubMenu,hChildMenu,1 
			mov edx,eax 
			invoke SendMessage,hwndClient,WM_MDISETMENU,hChildMenu,edx 
		.else 
			invoke GetSubMenu,hMainMenu,1    
			mov edx,eax 
			invoke SendMessage,hwndClient,WM_MDISETMENU,hMainMenu,edx 
		.endif    
		invoke DrawMenuBar,hwndFrame </pre>
<p><font face="MS Sans Serif" size="-1">When the MDI child window is created, 
  it monitors WM_MDIACTIVATE to see if it's the active window. It does this by 
  comparing the value of the lParam which contains the handle of the active child 
  window with its own handle. If they match, it's the active window and the next 
  step is to replace the menu of the frame window to its own. Since the original 
  menu will be replaced, you have to tell Windows again in which submenu the window 
  list should appear. That's why we must call <font color="#000099"><b>GetSubMenu</b></font> 
  again to retrieve the handle to the submenu. We send WM_MDISETMENU message to 
  the client window to achieve the desired result. wParam of WM_MDISETMENU contains 
  the handle of the menu you would like to replace the original menu. lParam contains 
  the handle of the submenu you want the window list to appear. Right after sending 
  WM_MDISETMENU, we call <font color="#000099"><b>DrawMenuBar</b></font> to refresh 
  the menu else your menu will be a mess.</font></p>
<pre>	.else 
		invoke DefMDIChildProc,hChild,uMsg,wParam,lParam 
		ret 
	.endif </pre>
<pre><font face="MS Sans Serif" size="-1">Within the window procedure of the MDI    child window, you must pass all unhandled messages to <font color="#000099"><b>DefMDIChildProc</b></font>    instead of <font color="#003399"><b>DefWindowProc</b></font>.</font></pre>
<pre>	.elseif ax==IDM_TILEHORZ 
		invoke SendMessage,hwndClient,WM_MDITILE,MDITILE_HORIZONTAL,0  
	.elseif ax==IDM_TILEVERT 
		invoke SendMessage,hwndClient,WM_MDITILE,MDITILE_VERTICAL,0  
	.elseif ax==IDM_CASCADE 
		invoke SendMessage,hwndClient,WM_MDICASCADE,MDITILE_SKIPDISABLED,0	 </pre>
<p><font face="MS Sans Serif" size="-1">When the user selects one of the menuitems 
  in the window submenu, we send the corresponding message to the client window. 
  If the user chooses to tile the windows, we send WM_MDITILE to the client window, 
  specifying in wParam what kind of tiling we want. WM_CASCADE is similar.</font></p>
<pre>	.elseif ax==IDM_CLOSE 
		invoke SendMessage,hwndClient,WM_MDIGETACTIVE,0,0    
		invoke SendMessage,eax,WM_CLOSE,0,0 </pre>
<pre><font face="MS Sans Serif" size="-1">If the user chooses &quot;Close&quot;    menuitem, we must obtain the handle of the currently active MDI child window    first by sending WM_MDIGETACTIVE to the client window. The return value in eax    is the handle of the currently active MDI child window. After that, we send    WM_CLOSE to that window.</font></pre>
<pre>	.elseif uMsg==WM_CLOSE 
		invoke MessageBox,hChild,addr ClosePromptMessage,addr AppName,MB_YESNO 
		.if eax==IDYES 
			invoke SendMessage,hwndClient,WM_MDIDESTROY,hChild,0    
		.endif </pre>
<p><font face="MS Sans Serif" size="-1">Within the window procedure of the MDI 
  child, when WM_CLOSE is received, it displays a message box asking the user 
  if he really wants to close the window. If the answer is yes, we send WM_MDIDESTROY 
  to the client window. WM_MDIDESTROY closes the MDI child window and restores 
  the title of the frame window.</font></p>
<hr>
<p align="center"><font face="MS Sans Serif" size="-1"><b>[<a href="http://win32asm.cjb.net">Iczelion's 
  Win32 Assembly Homepage</a>]</b></font></p>
<p>&nbsp;</p>
<pre>&nbsp;</pre>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -