青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

旅途

如果想飛得高,就該把地平線忘掉

超類化

 在這一講我們將學(xué)習(xí)什么是超類化以及它有什么作用;同時(shí)你還會(huì)學(xué)到怎樣在自己的窗口中用Tab鍵在控件中切換這一技巧。

理論:

在你的程序生涯中你肯定遇到過這樣的情況,你需要一系列的控件,但它們之間卻只有一點(diǎn)點(diǎn)的不同。例如,你可能需要10個(gè)只接受數(shù)字的 Edit 控件,當(dāng)然你可以通過多種方法來達(dá)到這個(gè)目的。

創(chuàng)建自己的類并用它實(shí)例化為那些控件
創(chuàng)建那些 Edit 控件并把它們?nèi)孔宇惢?
超類化Edit 控件
第一種方法太 乏味了,因?yàn)槟惚仨氉约簩?shí)現(xiàn)Edit 控件的每個(gè)功能,但這項(xiàng)工作不是輕松就能完成的。第二種方法好于第一種,但仍然要做許多工作,子類化幾個(gè)Edit 控件還可以接受,但若要子類化十幾二十個(gè),這項(xiàng)工作簡直就是一場惡夢。在這種情況下就應(yīng)該使用超類化這個(gè)技巧,它是用于控制某一個(gè)特定窗口類的特殊方法。 通過這種控制就可以修改窗口類的特性使之符合你的要求,然后再創(chuàng)建那一堆控件就可以了。

超類化有如下幾個(gè)步驟:

通過調(diào)用 GetClassInfoEx 來獲得想要進(jìn)行超類化操作的窗口類的信息。函數(shù)GetClassInfoEx 需要一個(gè)指向 WNDCLASSEX 結(jié)構(gòu)的指針,用于當(dāng)成功返回時(shí)填入窗口類的信息。
按需要修改 WNDCLASSEX 結(jié)構(gòu)的成員,其中有兩個(gè)成員必須修改:
hInstance 存放程序的實(shí)例句柄
lpszClassName 指向一個(gè)新類名的指針
不必修改成員 lpfnWndProc,但大多數(shù)情況下還是需要的。但要記住如果要使用函數(shù) CallWindowProc 調(diào)用老窗口的過程,那就必須保存成員 lpfnWndProc 的原值。
注冊修改完的 WNDCLASSEX 結(jié)構(gòu),得到一個(gè)具有舊窗口類某些特性的新窗口類。
用新窗口類創(chuàng)建窗口
如果要?jiǎng)?chuàng)建具有相同特性的多個(gè)控件,超類化就比子類化要好。

舉例:

.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個(gè)窗口句柄的數(shù)組
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

WndProc proc uses ebx edi hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL wc:WNDCLASSEX
.if uMsg==WM_CREATE
mov wc.cbSize,sizeof WNDCLASSEX
invoke GetClassInfoEx,NULL,addr EditClass,addr wc
push wc.lpfnWndProc
pop OldWndProc
mov wc.lpfnWndProc, OFFSET EditWndProc
push hInstance
pop wc.hInstance
mov wc.lpszClassName,OFFSET OurClass
invoke RegisterClassEx, addr wc
xor ebx,ebx
mov edi,20
.while ebx<6
invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR OurClass,NULL,\
WS_CHILD+WS_VISIBLE+WS_BORDER,20,\
edi,300,25,hWnd,ebx,\
hInstance,NULL
mov dword ptr [hwndEdit+4*ebx],eax
add edi,25
inc ebx
.endw
invoke SetFocus,hwndEdit
.elseif uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
WndProc endp

EditWndProc PROC hEdit:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
.if uMsg==WM_CHAR
mov eax,wParam
.if (al>="0" && al<="9") || (al>="A" && al<="F") || (al>="a" && al<="f") || al==VK_BACK
;處理字符0~9,A~F,a~f,這幾個(gè)十六進(jìn)制數(shù)
.if al>="a" && al<="f"
sub al,20h
如果是字符a~f,則把它們變?yōu)榇髮?br>.endif
invoke CallWindowProc,OldWndProc,hEdit,uMsg,eax,lParam
ret
.endif
.elseif uMsg==WM_KEYDOWN
mov eax,wParam
.if al==VK_RETURN
invoke MessageBox,hEdit,addr Message,addr AppName,MB_OK+MB_ICONINFORMATION
invoke SetFocus,hEdit
.elseif al==VK_TAB
invoke GetKeyState,VK_SHIFT
test eax,80000000
.if ZERO?
invoke GetWindow,hEdit,GW_HWNDNEXT
.if eax==NULL
invoke GetWindow,hEdit,GW_HWNDFIRST
.endif
.else
invoke GetWindow,hEdit,GW_HWNDPREV
.if eax==NULL
invoke GetWindow,hEdit,GW_HWNDLAST
.endif
.endif
invoke SetFocus,eax
xor eax,eax
ret
.else
invoke CallWindowProc,OldWndProc,hEdit,uMsg,wParam,lParam
ret
.endif
.else
invoke CallWindowProc,OldWndProc,hEdit,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
EditWndProc endp
end start


分析

這個(gè)程序創(chuàng)建了一個(gè)在其客戶區(qū)有六個(gè)被修改的 Edit 控件的簡單窗口,這些 Edit控件只接受十六進(jìn)制的數(shù)字。實(shí)際上,這個(gè)例子是通過修改窗口了類化的例子得來的。這個(gè)程序開始和其它程序一樣,有趣的部分出現(xiàn)在主窗口被創(chuàng)建的時(shí)候:

.if uMsg==WM_CREATE
mov wc.cbSize,sizeof WNDCLASSEX
invoke GetClassInfoEx,NULL,addr EditClass,addr wc

必須用想進(jìn)行超類化操作的類數(shù)據(jù)填充 WNDCLASSEX 結(jié)構(gòu),在我們的例子中就是類 Edit ,記住在調(diào)用函數(shù) GetClassInfoEx 之前必須填寫成員 cbSize,否則函數(shù)調(diào)用 GetClassInfoEx不會(huì)在 WNDCLASSEX 結(jié)構(gòu)中填入正確的返回值。成功返回后,變量 wc中保存的就是想要?jiǎng)?chuàng)建一個(gè)新類所需要的所有信息。

push wc.lpfnWndProc
pop OldWndProc
mov wc.lpfnWndProc, OFFSET EditWndProc
push hInstance
pop wc.hInstance
mov wc.lpszClassName,OFFSET OurClass

現(xiàn)在必須修改變量 wc 的一些屬性:第一個(gè)要修改的就是指向窗口過程的指針。因?yàn)樵谛麓翱谶^程中函數(shù) CallWindowProx 要用到老窗口過程,因此得把它保存到一個(gè)變量中以便使用。這個(gè)技巧和在子類化中用到的一樣,只不過不是調(diào)用 SetWindowLong 而是直接修改 WNDCLASSEX 結(jié)構(gòu)罷了。接下來必須得為這個(gè)新類取個(gè)名字。

invoke RegisterClassEx, addr wc

當(dāng)所有這些都完成時(shí),注冊這個(gè)新類就會(huì)得到一個(gè)具有舊類某些特征的新類了。

xor ebx,ebx
mov edi,20
.while ebx<6
invoke CreateWindowEx,WS_EX_CLIENTEDGE,ADDR OurClass,NULL,\
WS_CHILD+WS_VISIBLE+WS_BORDER,20,\
edi,300,25,hWnd,ebx,\
hInstance,NULL
mov dword ptr [hwndEdit+4*ebx],eax
add edi,25
inc ebx
.endw
invoke SetFocus,hwndEdit

注冊完新類就可以創(chuàng)建基于它的窗口了:
在上面的程序片斷中,用寄存器 ebx 來保存已創(chuàng)建的窗口數(shù)目,用寄存器 edi 來保存窗口左上角的 y 坐標(biāo)。創(chuàng)建一個(gè)新窗口時(shí),把它的句柄保存在一個(gè)雙字的數(shù)組中,當(dāng)創(chuàng)建完所有的窗口后,設(shè)定輸入焦點(diǎn)為所創(chuàng)建的第一個(gè)窗口。

這時(shí)已經(jīng)有6個(gè)只能接受十六進(jìn)制數(shù)字的 edit 窗口控件了,替換的窗口過程處理了字符過濾,這實(shí)際上和在子類化中的例子是一樣的。但不必做子類化那些窗口的額外工作了。

在此程序中,通過使用 Tabs 鍵來在各個(gè) Edit 控件中切換來使得這個(gè)程序更加有趣。一般來說,如果使用對話框,對話框管理器會(huì)處理好所有這些問題,即:
按 下 Tabs 輸入焦點(diǎn)切換到下一個(gè)控件窗口中,按下 Shift-Tabs 輸入焦點(diǎn)切換到上一個(gè)控件窗口中;但一個(gè)簡單的窗口不具有這個(gè)功能,必須子類化它們以處理 Tabs 鍵。在這個(gè)例子中,不必一個(gè)一個(gè)去子類化已經(jīng)進(jìn)行過超類化操作的這些控件,可以使用一種集中控制切換策略。

.elseif al==VK_TAB
invoke GetKeyState,VK_SHIFT
test eax,80000000
.if ZERO?
invoke GetWindow,hEdit,GW_HWNDNEXT
.if eax==NULL
invoke GetWindow,hEdit,GW_HWNDFIRST
.endif
.else
invoke GetWindow,hEdit,GW_HWNDPREV
.if eax==NULL
invoke GetWindow,hEdit,GW_HWNDLAST
.endif
.endif
invoke SetFocus,eax
xor eax,eax
ret

上面是摘自于 EditWndClass 過程的程序片斷,它檢查用戶是否按下了 Tabs 鍵,若是就調(diào)用函數(shù) GetKeyState 來檢查 SHIFT 鍵是否也被同時(shí)按下了。函數(shù) GetKeyState 在寄存器 eax 中設(shè)立一個(gè)返回值,用于判斷某個(gè)特定的鍵是否被按下了,若按下了,則把 eax 的的最高位置1,否則把最高位清0。所以只要用 80000000h 來測試返回值就行了,若最高位是1則說明用戶按下了 SHIFT-Tabs,這需要單獨(dú)處理;否則說明只按下 Tabs 鍵,調(diào)用函數(shù) GetWindow 來獲得 hEdit 所指向窗口的下一個(gè)窗口句柄,若該函數(shù)返回 NULL ,說明這是當(dāng)前窗口是窗口鏈中最后一個(gè)窗口了,應(yīng)該通過以參數(shù) GW_HWNDFIRST 調(diào)用函數(shù) GetWindow 來卷回到窗口鏈中的第一個(gè)窗口控件。SHIFT-Tabs 的處理過程和這正好相反。

posted on 2007-07-18 00:08 旅途 閱讀(288) 評論(0)  編輯 收藏 引用 所屬分類: 深入windows

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲一区二区三区激情| 国产精品青草久久| 鲁大师成人一区二区三区| 国内精品久久久久久影视8 | 亚洲性图久久| 中文国产一区| 久久久久久9999| 亚洲精品黄色| 亚洲精品日韩精品| 国产精品毛片a∨一区二区三区|国| 亚洲一区三区在线观看| 亚洲欧美www| 在线观看欧美日韩国产| 91久久国产精品91久久性色| 欧美日韩免费一区二区三区| 午夜影视日本亚洲欧洲精品| 欧美一区在线视频| 亚洲精品护士| 一区二区三区精品国产| 国产手机视频精品| 欧美激情精品久久久| 欧美日韩精品一区| 久久久国际精品| 欧美激情二区三区| 久久精品国产一区二区电影 | 国产精品高潮呻吟| 久久久国产精品一区| 欧美va亚洲va香蕉在线| 亚洲一区二区欧美日韩| 久久精品国产清高在天天线| 亚洲精品日产精品乱码不卡| 亚洲一区二区三区视频| 1769国产精品| 亚洲一区二区三区四区视频| 亚洲国产专区| 午夜天堂精品久久久久| 黄色在线一区| 一区二区av在线| 亚洲激情视频| 欧美在现视频| 亚洲永久在线| 香蕉久久夜色精品| 一区二区三区视频在线观看| 亚洲欧美日韩国产精品| 美女国产一区| 久久午夜国产精品| 国产精品爱久久久久久久| 美女精品国产| 国产欧美日韩| 国产精品99久久久久久久vr| 亚洲片区在线| 久久久久99精品国产片| 亚洲综合丁香| 欧美日韩国产一中文字不卡| 免费不卡欧美自拍视频| 国产精品一级在线| 亚洲视频欧美视频| 国产女主播一区二区| 日韩视频免费在线观看| 亚洲韩国日本中文字幕| 一区二区三区精品久久久| 日韩午夜在线电影| 免费h精品视频在线播放| 久久手机精品视频| 国产视频亚洲| 99这里有精品| 一区二区三区欧美日韩| 欧美高清在线| 亚洲国内欧美| 亚洲福利视频一区二区| 亚洲欧美国产一区二区三区| 亚洲在线成人精品| 国产精品美女久久久| 一本综合精品| 亚洲欧美日韩国产成人精品影院| 国产精品播放| 亚洲免费视频成人| 久久国产婷婷国产香蕉| 国产日韩1区| 欧美专区在线观看| 媚黑女一区二区| 亚洲国产精品传媒在线观看| 久久久人成影片一区二区三区观看| 久久人人爽爽爽人久久久| 国产欧美日韩一区二区三区在线观看| 亚洲一区二区三区午夜| 欧美一区二区视频在线| 国产一区二区黄色| 午夜精品999| 久久亚洲综合色| 欧美一级久久久| 亚洲电影成人| 欧美日本不卡视频| 欧美在线视频一区二区三区| 欧美激情国产日韩精品一区18| 亚洲一区国产视频| 国内精品视频久久| 欧美午夜欧美| 模特精品在线| 久久成人综合网| 日韩一级黄色大片| 噜噜噜在线观看免费视频日韩| 亚洲夜间福利| 亚洲日本va午夜在线电影| 国产精品视频观看| 欧美电影免费观看| 久久久精品动漫| 亚洲免费一在线| 日韩午夜视频在线观看| 欧美aa在线视频| 久久成人一区二区| 中文国产成人精品久久一| 在线成人免费视频| 久久精品一区二区三区四区| 99精品欧美一区二区三区| 欧美二区不卡| 久久久爽爽爽美女图片| 午夜精品一区二区三区在线| 99re亚洲国产精品| 亚洲福利视频专区| 狠狠色狠狠色综合日日91app| 国产精品二区二区三区| 欧美美女日韩| 欧美激情一区二区在线| 免费在线视频一区| 麻豆成人av| 美女国内精品自产拍在线播放| 久久久在线视频| 久久久精品网| 久久不射2019中文字幕| 亚洲欧美第一页| 午夜精品视频在线观看一区二区| 亚洲一区二区三区在线看| 亚洲天堂成人在线视频| 一区二区三区精品视频在线观看 | 国产精品视频观看| 国产精品青草久久| 国产精品免费网站在线观看| 欧美天堂亚洲电影院在线观看| 欧美日韩国产va另类| 欧美伦理在线观看| 欧美日韩国产成人| 欧美日韩一区二区在线视频| 欧美日韩中文字幕在线| 国产精品h在线观看| 国产精品久久国产愉拍| 国产精品一级在线| 国产专区综合网| 国模一区二区三区| **性色生活片久久毛片| 91久久亚洲| 这里是久久伊人| 亚洲欧美卡通另类91av | 国产精品久久国产三级国电话系列 | 亚洲黄色在线视频| 亚洲精品资源美女情侣酒店| 日韩亚洲成人av在线| 亚洲图片激情小说| 欧美在线观看一二区| 久久婷婷国产综合精品青草| 免费91麻豆精品国产自产在线观看| 欧美激情亚洲另类| 日韩视频在线你懂得| 亚洲欧美国产毛片在线| 久久久久久久久伊人| 欧美国产日韩一区| 国产精品久久久久久久9999| 国外成人在线| 日韩一级在线观看| 久久国产精品久久国产精品| 麻豆成人91精品二区三区| 亚洲日本va午夜在线影院| 亚洲午夜精品久久久久久app| 久久成人精品视频| 欧美精品综合| 国产一区二区主播在线| 亚洲美洲欧洲综合国产一区| 香港久久久电影| 欧美国产一区二区| 亚洲在线成人| 欧美激情亚洲视频| 国产欧美日韩视频一区二区| 亚洲电影视频在线| 午夜日韩电影| 亚洲欧洲精品一区二区三区波多野1战4 | 欧美91大片| 国产精品欧美风情| 亚洲美女黄网| 久久久蜜桃一区二区人| 午夜久久影院| 欧美国产一区二区| 欧美一区久久| av不卡免费看| 亚洲欧美国产另类| 国产精品一区一区三区| 欧美国产在线电影| 久久深夜福利| 久久久久一区二区三区四区| 亚洲综合成人在线| 亚洲天堂久久|