📄 lion-tutorial22.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 22: Superclassing</p>
<hr size="1">
<strong> </strong> In this tutorial, we will learn about superclassing, what it
is and what it is for. You will also learn how to provide Tab key navigation to
the controls in your own window. <br>
Download the example <a href="files/tut22.zip">here</a>
<h3> Theory:</h3>
In your programming career, you will surely encounter a situation where you need
several controls with *slightly* different behavior. For example, you may need
10 edit controls which accept only number. There are several ways to achieve that
goal:
<ul>
<li> Create your own class and instantiate the controls</li>
<li> Create those edit control and then subclass all of them</li>
<li> Superclass the edit control</li>
</ul>
The first method is too tedious. You have to implement every functionality of
the edit control yourself. Hardly a task to be taken lightly. The second method
is better than the first one but still too much work. It is ok if you subclass
only a few controls but it's going to be a nightmare to subclass a dozen or so
controls. Superclassing is the technique you should use for this occasion. <br>
Subclassing is the method you use to *take control* of a particular window class.
By *taking control*, I mean you can modify the properties of the window class
to suit your purpose then then create the bunch of controls. <br>
The steps in superclassing is outlined below:
<ul>
<li> call GetClassInfoEx to obtain the information about the window class you
want to superclass. GetClassInfoEx requires a pointer to a WNDCLASSEX structure
which will be filled with the information if the call returns successfully.</li>
<li> Modify the WNDCLASSEX members that you want. However, there are two members
which you MUST modify:</li>
<ul>
<li> hInstance You must put the instance handle of your program into
this member.</li>
<li> lpszClassName You must provide it with a pointer to a new class
name.</li>
<br>
You need not modify lpfnWndProc member but most of the time, you need to do
it. Just remember to save the original lpfnWndProc member if you want to call
it with CallWindowProc.
</ul>
<li> Register the modifed WNDCLASSEX structure. You'll have a new window class
which has several characteristics of the old window class.</li>
<li> Create windows from the new class</li>
</ul>
Superclassing is better than subclassing if you want to create many controls with
the same characteristics.
<h3> Example:</h3>
<b>.386</b> <br>
<b>.model flat,stdcall</b> <br>
<b>option casemap:none</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>WM_SUPERCLASS equ WM_USER+5</b> <br>
<b>WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD</b> <br>
<b>EditWndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD</b>
<p><b>.data</b> <br>
<b>ClassName db "SuperclassWinClass",0</b> <br>
<b>AppName db "Superclassing Demo",0</b> <br>
<b>EditClass db "EDIT",0</b> <br>
<b>OurClass db "SUPEREDITCLASS",0</b> <br>
<b>Message db "You pressed the Enter key in the text box!",0</b>
<p><b>.data?</b> <br>
<b>hInstance dd ?</b> <br>
<b>hwndEdit dd 6 dup(?)</b> <br>
<b>OldWndProc dd ?</b>
<p><b>.code</b> <br>
<b>start:</b> <br>
<b> invoke GetModuleHandle, NULL</b> <br>
<b> mov hInstance,eax</b> <br>
<b> invoke WinMain, hInstance,NULL,NULL, 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 hwnd:HWND</b>
<p><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,NULL</b> <br>
<b> push hInst</b> <br>
<b> pop wc.hInstance</b> <br>
<b> mov wc.hbrBackground,COLOR_APPWORKSPACE</b> <br>
<b> mov wc.lpszMenuName,NULL</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 CreateWindowEx,WS_EX_CLIENTEDGE+WS_EX_CONTROLPARENT,ADDR
ClassName,ADDR AppName,\</b> <br>
<b> WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,CW_USEDEFAULT,\</b>
<br>
<b> CW_USEDEFAULT,350,220,NULL,NULL,\</b>
<br>
<b> hInst,NULL</b>
<br>
<b> mov hwnd,eax</b>
<p><b> .while TRUE</b> <br>
<b> invoke GetMessage, ADDR msg,NULL,0,0</b>
<br>
<b> .BREAK .IF (!eax)</b> <br>
<b> invoke TranslateMessage, ADDR
msg</b> <br>
<b> invoke DispatchMessage, ADDR msg</b>
<br>
<b> .endw</b> <br>
<b> mov eax,msg.wParam</b> <br>
<b> ret</b> <br>
<b>WinMain endp</b>
<p><b>WndProc proc uses ebx edi hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM</b>
<br>
<b> LOCAL wc:WNDCLASSEX</b> <br>
<b> .if uMsg==WM_CREATE</b> <br>
<b> mov wc.cbSize,sizeof WNDCLASSEX</b>
<br>
<b> invoke GetClassInfoEx,NULL,addr
EditClass,addr wc</b> <br>
<b> push wc.lpfnWndProc</b> <br>
<b> pop OldWndProc</b> <br>
<b> mov wc.lpfnWndProc, OFFSET EditWndProc</b>
<br>
<b> push hInstance</b> <br>
<b> pop wc.hInstance</b> <br>
<b> mov wc.lpszClassName,OFFSET OurClass</b>
<br>
<b> invoke RegisterClassEx, addr wc</b>
<br>
<b> xor ebx,ebx</b> <br>
<b> mov edi,20</b> <br>
<b> .while ebx<6</b> <br>
<b> invoke
CreateWindowEx,WS_EX_CLIENTEDGE,ADDR OurClass,NULL,\</b> <br>
<b>
WS_CHILD+WS_VISIBLE+WS_BORDER,20,\</b> <br>
<b>
edi,300,25,hWnd,ebx,\</b> <br>
<b>
hInstance,NULL</b> <br>
<b> mov dword
ptr [hwndEdit+4*ebx],eax</b> <br>
<b> add edi,25</b>
<br>
<b> inc ebx</b>
<br>
<b> .endw</b> <br>
<b> invoke SetFocus,hwndEdit</b> <br>
<b> .elseif uMsg==WM_DESTROY</b> <br>
<b> invoke PostQuitMessage,NULL</b>
<br>
<b> .else</b> <br>
<b> invoke DefWindowProc,hWnd,uMsg,wParam,lParam</b>
<br>
<b> ret</b> <br>
<b> .endif</b> <br>
<b> xor eax,eax</b> <br>
<b> ret</b> <br>
<b>WndProc endp</b>
<p><b>EditWndProc PROC hEdit:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD</b> <br>
<b> .if uMsg==WM_CHAR</b> <br>
<b> mov eax,wParam</b> <br>
<b> .if (al>="0" && al<="9")
|| (al>="A" && al<="F") || (al>="a" && al<="f") || al==VK_BACK</b>
<br>
<b> .if al>="a"
&& al<="f"</b> <br>
<b>
sub al,20h</b> <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -