;运行效果
;win32汇编环境,对话框中使框控件子类化的示例一
;窗口子类化,就是把某种控件,自已再打造一遍,加入自已的功能。比如弄个特殊形状的按钮,或只能输入特殊字符的编辑框
;当然,一般来说,这都是很麻烦的事儿。其它的语言,像VC之类的,有子类的概念,其原理也是这些,但是又进行了更复杂的封装。所以,知其然更知其所以然,很重要。
;这里的例子,是把默认的编辑框,弄成只能输入十六进制的编辑框。
;复制下面代码进RadAsm可直接编译。重要部分加备注。
;下面为asm文件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
; 自定义函数声明
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DlgProc PROTO :DWORD,:DWORD,:DWORD,:DWORD ;对话框窗口函数
EditWndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
; Equ 等值定义
ICO_MAIN equ 1000 ;图标
ID_EDIT01 equ 11
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data
DlgName db "MyDialog",0
szMsg db "提示",0
szMessage db "你按下了回车键",0
.data?
hInstance HINSTANCE ?
hwndEdit dd ?
OldWndProc dd ?
.const
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke DialogBoxParam, hInstance, ADDR DlgName,NULL, addr DlgProc, NULL
invoke ExitProcess,eax
DlgProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.if uMsg == WM_INITDIALOG
invoke LoadIcon,hInstance,ICO_MAIN ;加载图标
invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,eax
invoke GetDlgItem,hWnd,ID_EDIT01
mov hwndEdit,eax ;保存编辑框的句柄
invoke SetFocus,eax ;让编辑框得到焦点,就是程序启动后光标在编辑框里
invoke SetWindowLong,hwndEdit,GWL_WNDPROC,addr EditWndProc ;把原来的窗口函数地址替换为自定义窗口函数的地址
mov OldWndProc,eax
.elseif uMsg == WM_CLOSE
invoke EndDialog, hWnd,NULL
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
EditWndProc PROC hEdit:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD ;这个窗口函数是插入主窗口消息循环的函数,只截取了2个消息,即下面的 WM_CHAR 和 WM_KEYDOWN,其它的消息不管,仍交回原主窗口 WndProc 函数处理
.if uMsg == WM_CHAR ;截取了WM_CHAR消息,相当于在这个编辑框里按任何字符,都在这里面处理。而里面除了处理这十六个字符和删除键backspace键外,没有对其它字符的处理,所以会导致按其它的字符没有反应
mov eax,wParam
.if (al>="0" && al<="9") || (al>="A" && al<="F") || (al>="a" && al<="f") || al==VK_BACK
.if al>="a" && al<="f"
sub al,20h ;加上20h是让小写的变成大写的
.endif
invoke CallWindowProc,OldWndProc,hEdit,uMsg,eax,lParam ;如果在CHAR消息发生时,不是在这些范围内的字符,则返回这个地址 OldWndProc 函数继续执行,就是返回原来的主窗口WndProc函数执行其它消息
ret
.endif
.elseif uMsg == WM_KEYUP ;截取了WM_KEYUP消息,就是键盘弹起时发送的消息
mov eax,wParam
.if al == VK_RETURN ;如果按了回车键,则显示输入的是什么内容
invoke MessageBox,hEdit,addr szMessage,addr szMsg,MB_OK+MB_ICONINFORMATION
invoke SetFocus,hEdit
.else
invoke CallWindowProc,OldWndProc,hEdit,uMsg,wParam,lParam ;如果在按键消息发生时,不是按的回车键,则返回这个地址 OldWndProc 函数继续执行
ret
.endif
.else
invoke CallWindowProc,OldWndProc,hEdit,uMsg,wParam,lParam ;如果不是上面的 WM_CHAR 和 WM_KEYUP 消息,则返回这个地址 OldWndProc 函数继续执行
ret
.endif
xor eax,eax
ret
EditWndProc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
;下面为rc文件内容
#include "resource.h" //提示缺少该文件,可以在资源里下载
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define ICO_MAIN 1000 //图标
#define ID_EDIT01 11 //编辑框标识符
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN ICON "Main.ico"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//定义对话框
MyDialog DIALOG 10, 10, 150, 65
STYLE DS_CENTER | WS_CAPTION | WS_MINIMIZEBOX |
WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPED | DS_MODALFRAME | DS_3DLOOK
CAPTION "对话框程序模版"
FONT 11, "宋体"
BEGIN
ICON ICO_MAIN, -1, 10, 11, 18, 21
LTEXT "该编辑框只能输入十六进制数值:", -1, 30, 15, 150, 19
CONTROL "",ID_EDIT01,"Edit",WS_CHILDWINDOW|WS_VISIBLE|WS_TABSTOP|WS_BORDER,30, 35, 110, 12,WS_EX_CLIENTEDGE //设置单行普通编辑框
END