友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
八万小说网 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

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

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




            invoke  SendMessage;hWinEdit;EM_STREAMIN;SF_TEXT;addr @stES

程序中流入和流出操作的回调函数使用同一个子程序,通过设置EDITSTREAM结构的自定义值dwCookie字段来表示进行的是流入还是流出的操作,子程序中通过判断dwCookie参数是TRUE还是FALSE来决定进行读文件还是写文件的操作(读写文件的函数ReadFile和WriteFile的用法请参考第10章)。



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


第9章 通用控件


9。4 使用Richedit控件(9)

    
5。 查找和替换

在Richedit控件中可以通过发送EM_FINDTEXT或者EM_FINDTEXTEX消息来完成查找字符串的功能,EM_FINDTEXTEX消息是EM_FINDTEXT消息的扩展,它们的用法是:

invoke  SendMessage;hWinEdit;EM_FINDTEXT;uFlags;lpFindText

invoke  SendMessage;hWinEdit;EM_FINDTEXTEX;uFlags;lpFindTextEx

消息的wParam参数中的uFlags指定查找的选项,它可以是以下取值的组合:

●   FR_DOWN(2。0版本及以上使用)——向后查找,不设置的话表示向前查找。

●   FR_MATCHCASE——查找字符串区分大小写。

●   FR_WHOLEWORD——匹配整个单词。

EM_FINDTEXT的lParam参数指向一个FINDTEXT结构,而EM_FINDTEXTEX消息的lParam参数指向一个FINDTEXTEX结构,这两个结构的定义如下:

FINDTEXT STRUCT

  chrg              CHARRANGE    ;查找区域

  lpstrText        DWORD      ?   ;查找字符串地址

FINDTEXT ENDS

FINDTEXTEX STRUCT

  chrg              CHARRANGE   ;查找区域

  lpstrText        DWORD      ?   ;查找字符串地址

  chrgText         CHARRANGE   ;如果找到则在这里返回找到文字的起始/结束位置

FINDTEXTEX ENDS

可以看出,EM_FINDTEXTEX消息的扩展之处在于直接在chrgText字段中返回找到文字的区域,程序可以马上使用这个区域数据进行其他操作,而EM_FINDTEXT消息必须根据找到的位置和查找字符串的长度自己计算这个区域。

两个消息的返回值是一样的,如果没有找到指定文字则返回?1,否则返回找到文字的起始位置。例子程序在_FindText子程序中完成查找功能,这个子程序分别在“查找下一个”、“查找上一个”和“查找文字”通用对话框的自定义消息中被调用,子程序中通过下面的代码来设置查找区域:

    invoke  SendMessage;hWinEdit;EM_EXGETSEL;0;addr @stFindText。chrg

    。if     stFind。Flags & FR_DOWN

            push        @stFindText。chrg。cpMax

            pop     @stFindText。chrg。cpMin

    。endif

    mov     @stFindText。chrg。cpMax;…1

当找到一个匹配字符串后,字符串被设置为选择区域,如果向下继续查找下一个的话,必须将这个选择区域的结束位置用做下一次查找的起始点,所以程序发送EM_EXGETSEL消息获取选择区域并将cpMax字段放到cpMin字段中,并将cpMax字段设置为…1,表示一直查找到全部文本的最后。

在第8章中已经有所介绍:“查找文字”通用对话框使用FINDREPLACE结构,不知道是巧合还是Microsoft的故意安排,FINDREPLACE结构中的Flags字段和EM_FINDTEXTEX消息中的wParam参数的标志定义是一样的,所以程序直接取出Flags字段,然后屏蔽掉FR_MATCHCASE,FR_DOWN和FR_WHOLEWORD等不需要使用的标志以后,就可以直接在消息的wParam参数中使用了:

    mov     ecx;stFind。Flags

    and     ecx;FR_MATCHCASE or FR_DOWN or FR_WHOLEWORD

    invoke  SendMessage;hWinEdit;EM_FINDTEXTEX;ecx;addr @stFindText

找到字符串以后,进行替换操作就不是一件复杂的事情了,因为FINDTEXTEX结构的chrgText字段中已经返回了找到文本的起始和结束位置,将它设置为选择区域以后就可以通过发送EM_REPLACESEL消息进行替换操作了。

9。4。3  Richedit控件的通知消息

Richedit控件也可以向父窗口发送多种通知消息,使用“可以”一词的意思是,控件在默认状态下并不发送通知消息,如果需要控件发送某个消息,必须首先对控件进行设置。通过向Richedit控件发送EM_SETEVENTMASK消息可以激活需要的通知消息:

    invoke  SendMessage;hWinEdit;EM_SETEVENTMASK;0;dwMask

dwMask是事件掩码,可以是下面标志的组合,分别代表激活不同的通知消息:

●   ENM_CHANGE——允许EN_CHANGE通知码,本消息在用户的操作可能改变控件中的文本的时候发送。

●   ENM_CORRECTTEXT——允许EN_CORRECTTEXT通知码。

●   ENM_DRAGDROPDONE——允许EN_DRAGDROPDONE通知码,本消息在用户完成了一个拖放操作后发送。

●   ENM_DROPFILES——允许EN_DROPFILES通知码,本消息在用户将一个文件拖放进控件后发送。

●   ENM_KEYEVENTS——允许为键盘消息发送EN_MSGFILTER通知码。

●   ENM_MOUSEEVENTS——允许为鼠标消息发送EN_MSGFILTER通知码。

●   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进制

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
返回目录 上一页 下一页 回到顶部 7 6
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!