一流信息监控拦截系统提醒您:很抱歉,由于您提交的内容中或访问的内容中含有系统不允许的关键词或者您的IP受到了访问限制,本次操作无效,系统已记录您的IP及您提交的所有数据。请注意,不要提交任何违反国家规定的内容!本次拦截的相关信息为:口交
翱?在这个对话框建立和关闭的时候,工具栏通过TBN_BEGINADJUST和TBN_ENDADJUST通知码来通知父窗口;每次按钮被调整的时候,发送的是TBN_TOOLBARCHANGE通知码;在按下对话框中的“帮助”按钮和“重置”按钮的时候,发送的是TBN_CUSTHELP和TBN_RESET通知码,对于这些通知码,父窗口可以不必响应,这并不会影响对话框的使用。

与对话框是否能够正常运行有关的通知码是TBN_QUERYINSERT,TBN_QUERYDELETE和TBN_GETBUTTONINFO,父窗口必须应答这些通知码。


图9.7  自定义工具栏对话框

当用户在指定位置插入一个按钮的时候,工具栏发送TBN_QUERYINSERT通知码询问父窗口是否允许此操作,这时lParam指向一个TBNOTIFY结构,这个结构定义如下:

TBNOTIFY STRUCT
 hdr           NMHDR     <> ;显然,这里肯定是NMHDR结构
 iItem         DWORD     ? ;按钮的位置索引
 tbButton      TBBUTTON <> ;包含按钮信息的TBBUTTON结构
 cchText       DWORD     ? ;pszText中字符串的长度
 pszText       DWORD     ? ;按钮的说明字符串
TBNOTIFY ENDS

如果程序允许在此按钮前面插入一个新按钮,那么返回TRUE,否则返回FALSE。另外当自定义对话框刚显示的时候,父窗口也会收到这个通知码,这时必须返回TRUE,否则对话框在屏幕上一闪就消失了。

当用户要删除一个按钮的时候,工具栏发送TBN_QUERYDELETE通知码,询问父窗口是否允许此操作,这时lParam也指向一个TBNOTIFY结构,用来说明将要删除的按钮,如果程序允许此操作则返回TRUE,否则返回FALSE。

   .elseif ([ebx + NMHDR.code] == TBN_QUERYINSERT) || \   
          ([ebx + NMHDR.code] == TBN_QUERYDELETE) ;现在ebx = lParam
          mov eax,TRUE
          ret

在例子程序中使用上面的代码来处理这两个通知码,也就是说对于全部的情况均返回TRUE,表示允许用户随意进行移动按钮和删除按钮的操作。

TBN_GETBUTTONINFO通知码的处理就比较复杂了,当工具栏需要全部按钮的信息的时候,会多次发送TBN_GETBUTTONINFO通知码,在例子程序中是这样处理的:

.elseif [ebx + NMHDR.code] == TBN_GETBUTTONINFO ;现在ebx = lParam
          assume ebx:ptr TBNOTIFY           ;lParam也是指向一个TBNOTIFY结构
          mov    eax,[ebx].iItem
          .if    eax < NUM_BUTTONS
                  mov    ecx,sizeof TBBUTTON
                  mul    ecx
                  add    eax,offset stToolbar
                  invoke RtlMoveMemory,addr [ebx].tbButton,eax,sizeof TBBUTTON
                  invoke LoadString,hInstance,[ebx].tbButton.idCommand,\
                        addr @szBuffer,sizeof @szBuffer
                  lea    eax,@szBuffer
                  mov    [ebx].pszText,eax
                  invoke lstrlen,addr @szBuffer
                  mov    [ebx].cchText,eax
                  assume ebx:nothing
                  mov    eax,TRUE
                  ret
           .endif

首先来分析为什么要这样处理TBN_GETBUTTONINFO通知码。

工具栏控件每次总是发送一组TBN_GETBUTTONINFO通知码,并且每次TBNOTIFY结构中的iItem字段递增,父窗口需要每次在结构中返回一个按钮的信息,如果还有剩余的按钮信息没有告诉工具栏(比如在用按钮和可选按钮加起来总共有15个,现在返回了10个,那么还剩5个按钮信息没有告诉工具栏),则在消息的返回值中返回TRUE,工具栏由此知道还有多余的按钮,于是马上将iItem字段加1再次发送TBN_GETBUTTONINFO通知码,如此循环直到某一次消息的返回值是FALSE为止。

为什么工具栏不知道需要获取的按钮的数量,而需要由父窗口来确定呢?这是因为工具栏只维护栏上现存的按钮,当工具栏上当前有10个按钮的时候,如果在一组TBN_GETBUTTONINFO通知码中返回了15个按钮,这15个按钮中包括了已经在使用的10个按钮和可以添加上去的另外5个按钮,那么工具栏就会将这15个按钮和栏上现存的所有按钮比较,并把现存的10个按钮放在“自定义工具栏”对话框的右边,把剩余的5个放在对话框的左边。

在例子中可用的按钮总共是16个,如果在初始化的时候只需要显示前面10个按钮,那么在使用CreateToolbarEx函数的时候可以只指定10个按钮,在这种情况下,当定制工具栏时在一组TBN_GETBUTTONINFO通知码中返回全部16个按钮的时候,多余的6个按钮就会出现在对话框的左边。

另外,TBNOTIFY结构的pszText需要返回按钮的说明文字,否则对话框中左右两个列表框中只会显示按钮图像而没有说明文字。程序在这里使用和工具提示信息同样的文字,这些文字存放在资源中,所以例子代码从TBNOTIFY结构包含的TBBUTTON结构中取出idCommand字段,使用LoadString函数从资源中读取以idCommand为ID的字符串并将其放入pszText所指的缓冲区中,最后使用lstrlen函数求出字符串的长度并放入cchText字段中,这样对话框的列表框中就可以显示出按钮的名称字符串了。

上页:第09章 通用控件 · 9.3 使用工具栏(5) 下页:第09章 通用控件 · 9.4 使用Richedit控件(1)

第09章 通用控件

版权所有 © 云南伯恩科技 证书:粤ICP备09170368号
/win32asm/win32asm-9-20.html">9.4 使用Richedit控件(8)
  • 9.4 使用Richedit控件(9)
  • 9.5 窗口的子类化(1)
  • 9.5 窗口的子类化(2)
  • 9.5 窗口的子类化(3)
  • 9.6 控件的超类化(1)
  • 9.6 控件的超类化(2)
  • 版权所有 © 云南伯恩科技 证书:粤ICP备09170368号