子类化:控件的子类化



说到类大家可能马上就想到C类首先是在C中提出但是这个概念在Win32Asm中仍然适用在类思路是这样:先假设某个对象有区别属性个新对象某个属性和上面所说对象有些区别而别属性那么实际上除了处理这个属性代码有些区别外代码完全可以使用前面对象代码在具体应用中我举个例子比如说我们定义个\"edit\"Control控件那么这个Control控件行为是由Windows内定窗口过程是在Windows系统内部但假如我们想编个有语法检查\"edit\"Control控件是否我们除了语法检查代码以外还要编写很多代码来实现老\"edit\"Control控件功能呢?答案当然是否定实际上我们可以截获个标准\"edit\"Control控件WM_CHAR消息检查键入键并做处理消息可以传给原来窗口过程示意如下:

在子类化的前:Windows=>editControl控件窗口过程

在子类化的后:Windows=>我们过程代码=>editControl控件窗口过程

在WindowsAPI中有个可以用来实现这个功能那就是SetWindowLongPROTOhWnd,nIndex,dwNewLong参数意思是hWnd是你要改变窗口句柄nIndex是我们要改变窗口什么属性值可以是GWL_EXSTYLE:改变窗口风格GWL_WNDPROC:设置窗口过程这正是我们感兴趣还有是GWL_USERDATA这是窗口自定义个32位数据dwNewLong是新还有个API是用来原来窗口过程叫CallWindwoProcPROTOlpPrevWndFunc,hWnd,Msg,wParam,lParam
我们在使用时有下面过程:

1.用SetWindowLong,hWnd,GWL_WNDPROC,addr_NewProcAddress设置我们自己代码地址API返回原来过程地址
2.用SetWindowLong,hWnd,GWL_USERDATA,eax把原来过程地址保存在自定义数据中

这样所有消息会先送到我们过程中然后在我们自己过程中对要处理消息进行处理如果不希望原来过程再处理那么返回对自己不处理消息原来窗口过程处理并把返回值返回思路方法是:

1.用invokeGetWindowLong,hWnd,GWL_USERDATA取出自定义数据中保存原过程地址
2.用invokeCallWindowProc,eax,hWnd,uMsg,wParam,lParam原过程UINTuStructSize}

本节教程提供了个源它是实现对话框中文本URL连接过程我们看到有文本是蓝色有下划线然后鼠标移动到上面会变手型就象浏览器中超联结而且按下会自动连接到网站WebSite上仔细想想我们并没有个标准Control控件或API来实现这样个功能这首先是个文本所以我们可以对这个文本进行子类化处理它WM_LBUTTONUP消息来实现按下自动连上网站WebSite功能;处理WM_SETCURSOR消息来让鼠标移到上面改变光标具体源如下:

-资源文件

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;************************************************
#

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Icon1000开始 [Page]
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#IDI_MAIN1000
#IDC_HANDLE2000

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;对话框3000开始
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#DLG_ABOUT3000

#ID_EMAIL3001
#ID_HOMEPAGE3002

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;资源定义开始
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
IDI_MAINICON\"Main.ico\"


IDC_HANDLECURSOR\"Handle.cur\"
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DLG_ABOUTDIALOGDISCARDABLE50,50,160,30
STYLEDS_MODALFRAME|WS_POPUP|WS_CAPTION|WS_SYSMENU
CAPTION\"URL联结文本演示-by罗云彬\"
FONT9,\"宋体\"
BEGIN
LTEXT\"我主页:\",-1,5,5,54,9
LTEXT\"http://asm.yeah.net\",ID_HOMEPAGE,55,5,80,9
LTEXT\"我E-mail:\",-1,5,17,54,9 [Page]
LTEXT\"[email protected]\",ID_EMAIL,55,17,95,9
END

-汇编源文件

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;是否包括调试代码
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DEBUG=0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Programmedby罗云彬,[email protected]
;Website:http://asm.yeah.net
;LuoYunBin’sWin32ASMpage(罗云彬编程乐园)
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;版本信息
;窗口子类化演示Ver1.0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

.386
.modelflat,stdcall
optionmap:none;sensitive

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Include数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

windows.inc [Page]
user32.inc
kernel32.inc
comctl32.inc
comdlg32.inc
shell32.inc
gdi32.inc

libuser32.lib
libkernel32.lib
libcomctl32.lib
libcomdlg32.lib
libshell32.lib
libgdi32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;Equ数据
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

IDI_MAINequ1000;icon
IDC_HANDLEequ2000;handlecursor

DLG_ABOUTequ3000;dialog-about
ID_EMAILequ3001
ID_HOMEPAGEequ3002

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>



.data?

hInstancedd?
hIcondd?

szBufferdb256dup(?)

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_HyperLinkProcproto:DWORD,:DWORD,:DWORD,:DWORD
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

.data

hCursorHandledd? [Page]
szHomePagedb\"http://asm.yeah.net\",0
szEmaildb\"mailto:[email protected]\"
db\"?subject=嗨!我喜欢你!\",0

.code

DEBUG
Debug.asm
end
;********************************************************************
;有关对话框中超级连接窗口
;********************************************************************
_HyperLinkProcprochWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

moveax,uMsg
.eaxWM_LBUTTONUP
invokeGetDlgCtrlID,hWnd
.eaxID_HOMEPAGE
invokeShellExecute,0,0,offszHomePage,0,0,0
.eaxID_EMAIL
invokeShellExecute,0,0,offszEmail,0,0,0
.end
.eaxWM_NCHITTEST
;将WM_NCHITTEST返回TRUE可以接收鼠标动作实现按下功能!
moveax,TRUE
ret
.eaxWM_SETCURSOR
invokeSetCursor,hCursorHandle
.
invokeGetWindowLong,hWnd,GWL_USERDATA
invokeCallWindowProc,eax,hWnd,uMsg,wParam,lParam
ret
.end
xoreax,eax
ret

_HyperLinkProcendp
;********************************************************************
;对话框窗口主
;********************************************************************
AboutDialogProcprocusesebxediesi,\\
hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
local@stWindow:RECT
local@dwWidth:DWORD,@dwHeight:DWORD
local@hWinTemp:DWORD
local@stFont:LOGFONT,@hFontOutput:DWORD

moveax,uMsg
.eaxWM_CLOSE
invokeEndDialog,hWnd,NULL
.eaxWM_INITDIALOG
invokeGetModuleHandle,NULL
invokeLoadCursor,eax,IDC_HANDLE
movhCursorHandle,eax
invokeGetDlgItem,hWnd,ID_HOMEPAGE
mov@hWinTemp,eax
invokeSetWindowLong,@hWinTemp,GWL_WNDPROC,addr_HyperLinkProc [Page]
invokeSetWindowLong,@hWinTemp,GWL_USERDATA,eax
invokeGetDlgItem,hWnd,ID_EMAIL
mov@hWinTemp,eax
invokeSetWindowLong,@hWinTemp,GWL_WNDPROC,addr_HyperLinkProc
invokeSetWindowLong,@hWinTemp,GWL_USERDATA,eax
.eaxWM_CTLCOLORSTATIC
invokeGetDlgCtrlID,lParam
.eaxID_HOMEPAGE||eaxID_EMAIL
invokeSendMessage,lParam,WM_GETFONT,0,0
mov@hFontOutput,eax
invokeGetObject,@hFontOutput,LOGFONT,addr@stFont
[email protected],TRUE
invokeCreateFontIndirect,addr@stFont
mov@hFontOutput,eax
invokeSelectObject,wParam,eax
invokeSetTextColor,wParam,Blue
invokeGetSysColor,COLOR_MENU
invokeSetBkColor,wParam,eax
invokeDeleteObject,@hFontOutput
;********************************************************************
;注意此处定要把StockOject返回值返回否则无法显示颜色
;********************************************************************
invokeGetStockObject,HOLLOW_BRUSH


.
moveax,FALSE
ret
.end
ret
.
;********************************************************************
;注意:对话框消息处理后要返回TRUE,对没有处理消息
;要返回FALSE
;********************************************************************
moveax,FALSE
ret
.end
moveax,TRUE
ret

AboutDialogProcendp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;开始
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> [Page]

start:
invokeInitCommonControls
invokeGetModuleHandle,NULL
movhInstance,eax
invokeDialogBoxParam,hInstance,DLG_ABOUT,\\
NULL,offAboutDialogProc,DLG_ABOUT
invokeExitProcess,NULL
;********************************************************************
endstart


分析和要点

在资源中我们定义了两个文本框ID分别为ID_HOMEPAGE和ID_EMAIL在主对话框过程initdialog消息中我们用GetDlgItem取它们hWnd然后进行子类化我们把新过程设置到了_HyperLinkProc中

invokeGetDlgItem,hWnd,ID_HOMEPAGE
mov@hWinTemp,eax
invokeSetWindowLong,@hWinTemp,GWL_WNDPROC,addr_HyperLinkProc
invokeSetWindowLong,@hWinTemp,GWL_USERDATA,eax
invokeGetDlgItem,hWnd,ID_EMAIL
mov@hWinTemp,eax
invokeSetWindowLong,@hWinTemp,GWL_WNDPROC,addr_HyperLinkProc
invokeSetWindowLong,@hWinTemp,GWL_USERDATA,eax


然后在新处理过程中检测到WM_LBUTTONUP消息(鼠标左键放开)就使用ShellExecuteAPI来连到网站WebSite检测WM_NCHITTEST来使文本Control控件接收鼠标消息检测WM_SETCURSOR消息把光标设置成手形对这些消息以外消息我们是不处理那就用CallWindowProc来原来过程进行处理

.eaxWM_LBUTTONUP
invokeGetDlgCtrlID,hWnd
.eaxID_HOMEPAGE
invokeShellExecute,0,0,offszHomePage,0,0,0
.eaxID_EMAIL
invokeShellExecute,0,0,offszEmail,0,0,0
.end
.eaxWM_NCHITTEST
;将WM_NCHITTEST返回TRUE可以接收鼠标动作实现按下功能!
moveax,TRUE
ret
.eaxWM_SETCURSOR
invokeSetCursor,hCursorHandle
.
invokeGetWindowLong,hWnd,GWL_USERDATA
invokeCallWindowProc,eax,hWnd,uMsg,wParam,lParam
ret
.end
Tags:  flash控件 activex控件 超类化 子类化

延伸阅读

最新评论

发表评论