超类化: 在这一讲我们将学习什么是超类化以及它有什么作用;同时你还会学到怎样在自己的窗口中用Tab键在控件中切换这一技巧。 理论: 在你的程序生涯中你肯定遇到过这样的情况,你需要一系列的控件,但它们之间却只有一点点的不同。例如,你可能需要10个只接受数字的 Edit 控件,当然你可以通过多种方法来达到这个目的。 创建自己的类并用它实例化为那些控件 创建那些 Edit 控件并把它们全部子类化 超类化Edit 控件 第一种方法太乏味了,因为你必须自己实现Edit 控件的每个功能,但这项工作不是轻松就能完成的。第二种方法好于第一种,但仍然要做许多工作,子类化几个Edit 控件还可以接受,但若要子类化十几二十个,这项工作简直就是一场恶梦。在这种情况下就应该使用超类化这个技巧,它是用于控制某一个特定窗口类的特殊方法。通过这种控制就可以修改窗口类的特性使之符合你的要求,然后再创建那一堆控件就可以了。 超类化有如下几个步骤: 通过调用 GetClassInfoEx 来获得想要进行超类化操作的窗口类的信息。函数GetClassInfoEx 需要一个指向 WNDCLASSEX 结构的指针,用于当成功返回时填入窗口类的信息。 按需要修改 WNDCLASSEX 结构的成员,其中有两个成员必须修改: hInstance 存放程序的实例句柄 lpszClassName 指向一个新类名的指针 不必修改成员 lpfnWndProc,但大多数情况下还是需要的。但要记住如果要使用函数 CallWindowProc 调用老窗口的过程,那就必须保存成员 lpfnWndProc 的原值。 注册修改完的 WNDCLASSEX 结构,得到一个具有旧窗口类某些特性的新窗口类。 用新窗口类创建窗口 如果要创建具有相同特性的多个控件,超类化就比子类化要好。 举例: .386 .model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib WM_SUPERCLASS equ WM_USER+5 WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD EditWndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD .data ClassName db "SuperclassWinClass",0 AppName db "Superclassing Demo",0 EditClass db "EDIT",0 OurClass db "SUPEREDITCLASS",0 Message db "You pressed the Enter key in the text box!",0 .data? hInstance dd ? hwndEdit dd 6 dup(?) ;存放6个窗口句柄的数组 OldWndProc dd ? ;原来的窗口过程 .code start: invoke GetModuleHandle, NULL mov hInstance,eax invoke WinMain, hInstance,NULL,NULL, SW_SHOWDEFAULT invoke ExitProcess,eax WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD LOCAL wc:WNDCLASSEX LOCAL msg:MSG LOCAL hwnd:HWND mov wc.cbSize,SIZEOF WNDCLASSEX mov wc.style, CS_HREDRAW or CS_VREDRAW mov wc.lpfnWndProc, OFFSET WndProc mov wc.cbClsExtra,NULL mov wc.cbWndExtra,NULL push hInst pop wc.hInstance mov wc.hbrBackground,COLOR_APPWORKSPACE mov wc.lpszMenuName,NULL mov wc.lpszClassName,OFFSET ClassName invoke LoadIcon,NULL,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,NULL,IDC_ARROW mov wc.hCursor,eax invoke RegisterClassEx, addr wc invoke CreateWindowEx,WS_EX_CLIENTEDGE+WS_EX_CONTROLPARENT,ADDR ClassName,ADDR AppName,\ WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_MINIMIZEBOX+WS_MAXIMIZEBOX+WS_VISIBLE,CW_USEDEFAULT,\ CW_USEDEFAULT,350,220,NULL,NULL,\ hInst,NULL mov hwnd,eax .while TRUE invoke GetMessage, ADDR msg,NULL,0,0 .BREAK .IF (!eax) invoke TranslateMessage, ADDR msg invoke DispatchMessage, ADDR msg .endw mov eax,msg.wParam ret WinMain endp [1] [2] [3] 下一页
|