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

📄 lion-tutorial20.htm

📁 内有一些代码
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<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 20: Window Subclassing</p>
<hr size="1">
<strong> </strong> In this tutorial, we will learn about window subclassing, what 
it is and how to use it to your advantage. <br>
Download the example <a href="files/tut20.zip">here</a>. 
<h3> Theory:</h3>
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. <br>
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. 
<br>
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: 
<ul>
  <h4> Before Subclassing</h4>
  Windows ==> edit control's window procedure 
  <h4> After Subclassing</h4>
  Windows ==> our window procedure -----> edit control's window procedure 
</ul>
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. <br>
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. <br>
We can do that by calling SetWindowLong. 
<ul>
  <b>SetWindowLong PROTO hWnd:DWORD, nIndex:DWORD, dwNewLong:DWORD</b> 
</ul>
hWnd = handle of the window to change the value in the WNDCLASSEX structure <br>
nIndex == value to change. 
<ul>
  <b>GWL_EXSTYLE</b> Sets a new extended window style. <br>
  <b>GWL_STYLE</b> Sets a new window style. <br>
  <b>GWL_WNDPROC</b> Sets a new address for the window procedure. <br>
  <b>GWL_HINSTANCE</b> Sets a new application instance handle. <br>
  <b>GWL_ID</b> Sets a new identifier of the window. <br>
  <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. 
</ul>
dwNewLong = the replacement value. <br>
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. <br>
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. 
<ul>
  <b>CallWindowProc PROTO lpPrevWndFunc:DWORD, \</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  hWnd:DWORD,\</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  Msg:DWORD,\</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  wParam:DWORD,\</b> <br>
  <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
  lParam:DWORD</b> 
</ul>
lpPrevWndFunc = the address of the original window procedure. <br>
The remaining four parameters are the ones passed to our window procedure. We 
just pass them along to CallWindowProc. 
<h4> Code Sample:</h4>
<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>include \masm32\include\comctl32.inc</b> <br>
<b>includelib \masm32\lib\comctl32.lib</b> <br>
<b>includelib \masm32\lib\user32.lib</b> <br>
<b>includelib \masm32\lib\kernel32.lib</b> 
<p><b>WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD</b> <br>
  <b>EditWndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD</b> 
<p><b>.data</b> <br>
  <b>ClassName&nbsp; db "SubclassWinClass",0</b> <br>
  <b>AppName&nbsp;&nbsp;&nbsp; db "Subclassing Demo",0</b> <br>
  <b>EditClass&nbsp; db "EDIT",0</b> <br>
  <b>Message&nbsp; db "You pressed Enter in the text box!",0</b> 
<p><b>.data?</b> <br>
  <b>hInstance&nbsp; HINSTANCE ?</b> <br>
  <b>hwndEdit dd ?</b> <br>
  <b>OldWndProc dd ?</b> 
<p><b>.code</b> <br>
  <b>start:</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke GetModuleHandle, NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; hInstance,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke WinMain, hInstance,NULL,NULL, SW_SHOWDEFAULT</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; invoke ExitProcess,eax</b> 
<p><b>WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; LOCAL wc:WNDCLASSEX</b> <br>
  <b>&nbsp;&nbsp;&nbsp; LOCAL msg:MSG</b> <br>
  <b>&nbsp;&nbsp;&nbsp; LOCAL hwnd:HWND</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.cbSize,SIZEOF WNDCLASSEX</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.style, CS_HREDRAW or CS_VREDRAW</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.lpfnWndProc, OFFSET WndProc</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.cbClsExtra,NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.cbWndExtra,NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; push&nbsp; hInst</b> <br>
  <b>&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp; wc.hInstance</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hbrBackground,COLOR_APPWORKSPACE</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.lpszMenuName,NULL</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.lpszClassName,OFFSET ClassName</b> 
  <br>
  <b>&nbsp;&nbsp;&nbsp; invoke LoadIcon,NULL,IDI_APPLICATION</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hIcon,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hIconSm,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke LoadCursor,NULL,IDC_ARROW</b> <br>
  <b>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp; wc.hCursor,eax</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke RegisterClassEx, addr wc</b> <br>
  <b>&nbsp;&nbsp;&nbsp; invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR ClassName,ADDR 
  AppName,\</b> <br>
  <b>&nbsp;WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,CW_USEDEFAULT,\</b> 
  <br>

⌨️ 快捷键说明

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