?? tut20.html
字號:
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Iczelion">
<meta name="GENERATOR" content="Mozilla/4.51 [en] (Win95; I) [Netscape]">
<title>Iczelion's Win32asm Tutorial 20: Window Subclassing</title>
</head>
<body text="#FFFFFF" bgcolor="#000080" link="#FFFF00" vlink="#8080FF" alink="#FF00FF">
<center>
<h1>
<font face="Arial,Helvetica"><font color="#FFFF99">Tutorial 20: Window
Subclassing</font></font></h1></center>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>In this
tutorial, we will learn about window subclassing, what it is and how to
use it to your advantage.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Download
the example <a href="files/tut20.zip">here</a>.</font></font></font>
<h3>
<font face="Arial,Helvetica"><font color="#009900"><font size=+0>Theory:</font></font></font></h3>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>If you
program in Windows for some time, you will find some cases where a window
has <i>nearly</i> the attributes you need in your program but not quite.
Have you encountered a situation where you want some special kind of edit
control that can filter out some unwanted text? The straightforward thing
to do is to code your own window. But it's really hard work and time-consuming.
Window subclassing to the rescue.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>In
a nutshell, window subclassing allows you to "take over" the subclassed
window. You will have absolute control over it. Let's take an example to
make this clearer. Suppose you need a text box that accepts only hex numbers.
If you use a simple edit control, you have no say whatsoever when your
user types something other than hex numbers into your text box, ie. if
the user types "zb+q*" into your text box, you can't do anything with it
except rejecting the whole text string. This is <i>unprofessional</i> at
least. In essence, you need the ability to examine each character the user
typed into the text box right at the moment he typed it.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>We
will examine how to do that now. When the user types something into a text
box, Windows sends WM_CHAR message to the edit control's window procedure.
This window procedure resides inside Windows itself so we can't modify
it. <b>But we can redirect the message flow to our own window procedure</b>.
So that our window procedure will get first shot at any message Windows
sends to the edit control. If our window procedure chooses to act on the
message, it can do so. But if it doesn't want to handle the message, it
can pass it to the original window procedure. This way, our window procedure
inserts itself between Windows and the edit control. Look at the flow below:</font></font></font>
<ul>
<h4>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Before
Subclassing</font></font></font></h4>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Windows
==> edit control's window procedure</font></font></font>
<h4>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>After
Subclassing</font></font></font></h4>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Windows
==> our window procedure -----> edit control's window procedure</font></font></font></ul>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Now we
put our attention on how to subclass a window. Note that subclassing is
not limited to controls, it can be used with any window.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Let's
think about how Windows knows where the edit control's window procedure
resides. A guess?......lpfnWndProc member of WNDCLASSEX structure. If we
can replace this member with the address of our own window procedure, Windows
will send messages to our window proc instead.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>We
can do that by calling SetWindowLong.</font></font></font>
<ul><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>SetWindowLong
PROTO hWnd:DWORD, nIndex:DWORD, dwNewLong:DWORD</font></font></font></b></ul>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>hWnd =
handle of the window to change the value in the WNDCLASSEX structure</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>nIndex
== value to change.</font></font></font>
<ul><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1><b>GWL_EXSTYLE</b>
Sets a new extended window style.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1><b>GWL_STYLE</b>
Sets a new window style.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1><b>GWL_WNDPROC</b>
Sets a new address for the window procedure.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1><b>GWL_HINSTANCE</b>
Sets a new application instance handle.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1><b>GWL_ID</b>
Sets a new identifier of the window.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1><b>GWL_USERDATA</b>
Sets the 32-bit value associated with the window. Each window has a corresponding
32-bit value intended for use by the application that created the window.</font></font></font></ul>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>dwNewLong
= the replacement value.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>So
our job is easy: We code a window proc that will handle the messages for
the edit control and then call SetWindowLong with GWL_WNDPROC flag, passing
along the address of our window proc as the third parameter. If the function
succeeds, the return value is the previous value of the specified 32-bit
integer, in our case, the address of the original window procedure. We
need to store this value for use within our window procedure.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Remember
that there will be some messages we don't want to handle, we will pass
them to the original window procedure. We can do that by calling CallWindowProc
function.</font></font></font>
<ul><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>CallWindowProc
PROTO lpPrevWndFunc:DWORD, \</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>
hWnd:DWORD,\</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>
Msg:DWORD,\</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>
wParam:DWORD,\</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>
lParam:DWORD</font></font></font></b></ul>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>lpPrevWndFunc
= the address of the original window procedure.</font></font></font>
<br><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>The
remaining four parameters are the ones passed to our window procedure.
We just pass them along to CallWindowProc.</font></font></font>
<h4>
<font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>Code Sample:</font></font></font></h4>
<b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>.386</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>.model
flat,stdcall</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>option
casemap:none</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>include
\masm32\include\windows.inc</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>include
\masm32\include\user32.inc</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>include
\masm32\include\kernel32.inc</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>include
\masm32\include\comctl32.inc</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>includelib
\masm32\lib\comctl32.lib</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>includelib
\masm32\lib\user32.lib</font></font></font></b>
<br><b><font face="Arial,Helvetica"><font color="#FFFFFF"><font size=-1>includelib
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -