友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
合租小说网 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

windows环境下32位汇编语言程序设计-第59部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!



●   ENM_PROTECTED——允许发送EN_PROTECTED通知码。

●   ENM_SCROLL——允许发送EN_HSCROLL和EN_VSCROLL通知码。

●   ENM_SCROLLEVENTS——允许为鼠标滑轮发送EN_MSGFILTER通知码。

●   ENM_SELCHANGE——允许发送EN_SELCHANGE通知码,本消息在选择区域改变以后发送(包括光标位置改变)。

●   ENM_UPDATE——允许发送EN_UPDATE通知码,本消息在控件将要显示被改变的文本之前发送。

当这些通知消息被激活的时候,父窗口就可以收到包含相应通知码的WM_NOTIFY消息。一般来说,将控件设置为仅发送程序感兴趣的通知消息,如当在Richedit控件中按下右键需要弹出一个菜单的时候,需要检测鼠标消息,那么就需要指定ENM_MOUSEEVENTS标志;另外,如果需要随时检测选择区域的状态,以便随时设置工具栏中“拷贝”与“剪切”等按钮的状态,那么就要使用ENM_SELCHANGE标志,这样光标一移动或者选择区域一改变,父窗口就可以收到EN_SELCHANGE通知码,于是程序就可以在WM_NOTIFY消息中随时改变工具栏上各按钮的状态。

由于Richedit。asm例子中没有使用工具栏,所以没有对通知消息进行示例,有兴趣的读者可以查看所附光盘的Chapter09Wordpad目录中的例子文件,这个例子中使用工具栏和状态栏等控件,需要随时显示光标位置等信息,程序中就包含了处理通知消息的代码。



 
来源:电子工业出版社 作者:罗云彬 上一页         回书目         下一页          
上一页         回书目         下一页          
  


第9章 通用控件


9。5 窗口的子类化(1)

    
9。5。1  什么是窗口的子类化

在使用控件的过程中,常常会遇到这样一种情况:我们需要一种窗口,它和某种现成的控件提供的功能很相似,如果使用现成控件的话,那么控件几乎能提供所有需要的功能,仅我们要求的某个细节无法实现。举例来说,要编写一个16进制与10进制的转换程序,程序中需要两个编辑控件来输入数值,输入10进制数值可以使用现成的Edit控件,只要指定ES_NUMBER风格就能让编辑框只能输入数字0~9,但输入16进制数值的时候就不行了,因为指定ES_NUMBER风格的话就无法输入A~F,不指定的话用户就可能输入0~9和A~F之外的东西,那么该如何处理呢?

解决的办法有两种,第一种当然是自己创建一个窗口类,然后在自己的窗口过程中完成所有的功能,这显然是一项费时又费力的工作,因为我们几乎要自己重新写一遍Edit控件的全部功能;第二种方法就是使用本节要介绍的窗口子类化,窗口子类化最适合做的就是这一类工作。

窗口子类化的含义是接管被子类化的控件窗口,以达到对它进行控制的目的。虽然控件的窗口过程被封装在Windows内部,无法对它进行直接修改,但只要能截获Windows给控件的窗口过程发送的消息,就能够控制控件窗口。以上面的要求为例,只要截获Windows向编辑控件发送的WM_CHAR消息,就能够根据需要丢弃包含非16进制字符的WM_CHAR消息,只把包含16进制字符的WM_CHAR转发给控件的窗口过程,这样编辑控件将根本收不到16进制字符之外的字符,我们的要求也就达到了。

控件窗口子类化的流程如图9。8所示。

子类化的操作并不局限于控件窗口,实际上任何窗口都可以子类化。但是对于应用程序自身使用的窗口类来说,它的控制权本来就是100%属于应用程序自身的,要实现某种功能就直接修改源代码好了,没有必要再进行一个子类化的过程,所以子类化的操作往往是对“黑匣子”类型的控件窗口进行的。


图9。8  窗口子类化的工作原理

9。5。2  窗口子类化的实现

窗口子类化的要点是截获窗口的窗口过程,如何实现这一点呢?每个窗口的内部都保存有它所属的窗口类的WNDCLASSEX 结构,结构中的lpfnWndProc字段指出了窗口过程的地址,如果能用自己的窗口过程地址来替换这个地址,那么Windows就会把消息发送到自定义的窗口过程中来了。通过调用函数SetWindowLong可以实现这个功能,SetWindowLong函数的用法是这样的:

    invoke  SetWindowLong;hWnd;nIndex;dwNewLong

    mov dwOldLong

hWnd参数指定要子类化窗口的窗口句柄,nIndex参数指定需要修改窗口的哪个属性,它可以是以下的取值:

●   GWL_EXSTYLE——窗口的扩展风格。

●   GWL_STYLE——窗口风格。

●   GWL_WNDPROC——窗口过程地址(这就是我们需要的)。

●   GWL_HINSTANCE——窗口所属的模块实例句柄。

●   GWL_ID——窗口ID。

●   GWL_USERDATA——窗口附带的32位自定义数值。

 dwNewLong参数指定新的属性值。如果nIndex为GWL_WNDPROC,dwNewLong表示新的窗口过程地址;如果nIndex为GWL_STYLE,dwNewLong则表示新的窗口风格,依此类推。函数的返回值是指定属性的原先数值。当函数用于窗口子类化的时候,在nIndex参数中使用GWL_WNDPROC,以便将窗口过程地址设置到自定义的子程序中,这时函数返回的是控件窗口原来的窗口过程地址,由于窗口子类化的出发点就是为了尽量使用控件窗口原有的功能,程序为了“偷懒”而不去处理的大部分消息还要靠原来的窗口过程来处理,所以这个地址必须被保存下来。

让我们通过一个简单的例子来演示窗口子类化的实现过程,程序实现的就是前面介绍的16进制与10进制转换的程序,源代码位于所附光盘的Chapter09SubClass目录中。程序首先在资源脚本文件SubClass。rc中定义了一个对话框,对话框中包括两个编辑控件,IDC_DEC用来输入10进制数值,它包含ES_NUMBER风格,只能输入0~9的数值;而IDC_HEX用来输入16进制数值,代码如下:

//》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

#include                    

//》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

#define ICO_MAIN            1000

#define DLG_MAIN            1000

#define IDC_HEX         1001

#define IDC_DEC         1002

//》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

ICO_MAIN        ICON            〃Main。ico〃

//》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

DLG_MAIN DIALOG 107; 102; 129; 42

STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU

CAPTION 〃Hex  Dec〃

FONT 9; 〃宋体〃



 LTEXT 〃Hex〃; …1; 7; 9; 15; 8

 EDITTEXT IDC_HEX; 27; 7; 94; 12

 LTEXT 〃Dec〃; …1; 7; 26; 15; 8

 EDITTEXT IDC_DEC; 27; 24; 94; 12; ES_NUMBER



汇编源程序SubClass。asm的内容如下:

                    。386

                    。model flat; stdcall

                    option casemap :none

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; Include 文件定义

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

include         windows。inc

include         user32。inc

includelib      user32。lib

include         kernel32。inc

includelib      kernel32。lib

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; Equ 等值定义

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

ICO_MAIN            equ     1000

DLG_MAIN            equ     1000

IDC_HEX         equ     1001



 
来源:电子工业出版社 作者:罗云彬 上一页         回书目         下一页          
上一页         回书目         下一页          
  


第9章 通用控件


9。5 窗口的子类化(2)

    
IDC_DEC         equ     1002

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; 数据段

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

                    。data?

hInstance       dd      ?

hWinMain            dd      ?

dwOption            dd      ?

lpOldProcEdit   dd      ?

                    nst

szFmtDecToHex   db      '%08X';0

szFmtHexToDec   db      '%u';0

szAllowedChar   db      '0123456789ABCDEFabcdef';08h

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; 代码段

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

                    de

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; IDC_HEX编辑框的新窗口过程

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

_ProcEdit       proc        uses ebx edi esi hWnd;uMsg;wParam;lParam

 

                    mov     eax;uMsg

                    。if     uMsg  WM_CHAR

                            mov     eax;wParam

                            mov     edi;offset szAllowedChar

                            mov     ecx;sizeof szAllowedChar

                            repnz   scasb

                            。if     ZERO?

                                    。if     al 》 '9'

                                            and al;not 20h

                                    。endif

                                    invoke  CallWindowProc;lpOldProcEdit;

                                            hWnd;uMsg;eax;lParam

                                    ret

                            。endif

                    。else

                            invoke  CallWindowProc;lpOldProcEdit;

                                    hWnd;uMsg;wParam;lParam

                            ret

                    。endif

                    xor     eax;eax

                    ret

 

_ProcEdit       endp

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; 计算16进制到10进制

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

_HexToDec       proc

                    local   @szBuffer'512':byte

 

                    invoke  GetDlgItemText;hWinMain;IDC_HEX;

                            addr @szBuffer;sizeof @szBuffer

                    lea     esi;@szBuffer

                    cld

                    xor     eax;eax

                    mov     ebx;16

                    。while  TRUE

                            movzx   ecx;byte ptr 'esi'

                            inc     esi

                            。break  。if ! ecx

                            。if     cl 》 '9'

                                    sub     cl;'A' … 0ah

                            。else

                                    sub     cl;'0'

                            。endif

                            mul     ebx

                            add     eax;ecx

                    。endw

                    invoke  wsprintf;addr @szBuffer;addr szFmtHexToDec;eax

                    invoke  SetDlgItemText;hWinMain;IDC_DEC;addr @szBuffer

                    ret

 

_HexToDec       endp

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; 计算10进制到16进制

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

_DecToHex       proc

                    local   @szBuffer'512':byte

 

                    invoke  GetDlgItemInt;hWinMain;IDC_DEC;NULL;FALSE

                    invoke  wsprintf;addr @szBuffer;addr szFmtDecToHex;eax

                    invoke  SetDlgItemText;hWinMain;IDC_HEX;addr @szBuffer

                    ret

 

_DecToHex       endp

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

_ProcDlgMain        proc        uses ebx edi esi hWnd;wMsg;wParam;lParam

 

                    mov     eax;wMsg

;********************************************************************

                    。if     eax   WM_CLOSE

          
返回目录 上一页 下一页 回到顶部 0 0
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!