http://blog.chinaunix.net/uid-28596231-id-3515974.html
先说说CToolBar是怎么使用的?
一个CToolBar需要有工具条对应的位图,位图的每一块图标应该有自己的ID,对应的处理方法。
这样的就会有两种方法,可以看做Wizard和非Wizard(笔者自己理解的)
主要由两种方法:
法一(wizard):
1.建立工具条资源 (建立一个资源,包含了位图,在资源头文件中标注了ID)
2.建立工具条对象结构(建立一个工具栏对象)
3.调用函数建立工具条对象并绑定(初始化内部结构,具体内部干啥了笔者也不清楚,大概也就是设置风格,申请空间之类的事情,不过各种看官可以自己追踪下,处于一种负责的态度,我还是把MSDN的翻译说说:创建一个windows的工具栏,并与CToolBar对象相联)
4.调用LoadToolBar调入工具条资源(工具栏已经开始占用内存了,但没有实质内容啊,可以想象,内部诸如应该有m_bmp等私有变量,这时候需要与第一步生成的资料建立关联,这样一个工具栏就完成了)
法二(非wizard):
1.建立工具条对象(声明一个对象)
2.调用建立函数并绑定对象(创立对象)
3.调入包含按钮的位图(载入位图)
4.用SetButtons函数设置按钮风格并与位图建立联系。(确定ID)
后两步相当于法一中的1和4。都是载入资源,标记ID。
下面详细讲讲这几个步骤:
第一就是资源:
工具条的一个重要目的是美观,所以图标的好看与否很关键,VS的编辑图片能力不强,很多牛人喜欢自己制作图标。那么这位图有什么要求呢?不是所有的图片都能当工具栏的
所有按钮位图均存放在一个位图文件中,按钮位图的大小相同,默认为16点宽、15点高,位图必须从左至右存放。设置按钮函数具有指向一组控制标识符ID的 指针和索引值,用来确定每个按钮的位置,如果存在分隔符ID_SEPARATOR, 那么该图像就不存在索引值。正常情况下工具条中的按钮都是单排从左至右排列的,可以通过SetButtonInfo函数改变排序规则。 工具条中最终形成的按钮大小相同,均为24 x 22 象素,每个按钮只对象一幅图像。工具条中的按钮默认为下推按钮,通过设置TBBS_CHECKBOX风格可以实现检查盒按钮,通过调用SetRadio成 员函数可以实现无线按钮。
第二就是Create
Create( CWnd* pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_TOP,
UINT nID = AFX_IDW_TOOLBAR );
其中参数pParentWnd用来确定指向工具条父窗口的指针;参数dwStyle用来确定工具条的风格,其取值如下;参数nID用来确定工具条子窗口的标识符。
剩下载入和编辑ID,纯属无脑操作,见MSDN
ToolBar的各种风格,见MSDN或者百度,我就不赘述了。
然后说说CMFCToolBar
在vs2008版本后,出现了一系列的类CMFCReBar,CMFCToolBar,CMFCStatusBar等等,这里写这个纯属不得已,因为你wizard出来的都是这些,总不能无视吧?而且这部分资料网上没多少。我就把我的见解说说哈。
说实话,这个类和CToolBar基本用法都是一样的
步骤:添加一个工具栏,然后绘图,为每一个图标添加一个ID,
系统会自动给你生成一副相对应的bmp图片。(要求矩形开始15*16,这个不知道怎么修改,没研究,需要的时候再看)
然后再OnCreate里面的
m_ toolbar1.LoadToolBar(TOOL_ID);
最后,为每个ID写处理函数(如果以前写过就不用了)
貌似完全一样啊。
但是我在做一个小项目的时候发现了一个现象
CReBar添加CMFCToolBar的时候无法显示图标,CToolBar就可以,不知道是不是我哪里出了个小错误,我就不瞎说误人子弟了。
是不是需要CMFCReBar充当容器呢?没试过,各位试过的留言,指点我一下子,谢谢了。
(你是不是觉得CMFCToolBar的解释坑爹了,其实真是这样,这个类貌似真是差不多,如果遇到不一样的问题留言,我们一起讨论)
最后呢?也是让我头疼了一下子 的一个类CReBar
头疼在哪里呢?
我把问题列举下,看看会不会让你头疼。
CToolBar的父窗口是CMainFrame的窗口,因为create的时候第一个参数是this,指的是唯一的CMainFrame的对象。那CReBar就不是CToolBar的父窗口了,这两个Bar什么关系?
为了探究上面的问题,笔者进行了代码的跟踪调试,通过一些指针弄懂了这些问题。
CWnd *pAddressParent=m_wndAddress.GetParent();
CWnd *pToolParent=m_wndTool.GetParent();
CWnd *pRebarParent=m_wndReBar.GetParent();
CWnd *pToolBarParent=m_wndToolBar.GetParent();
查看这些的数值,发现下面的问题
CToolBar和CComboBox创建的时候,create(this),所以父窗口是CMainFrame对象。
但是当执行过m_wndReBar.AddBar这句话后,他们的父窗口变成了m_wndReBar。
可见这里有一个改变父窗口的操作(具体实现我跟踪了AddBar,但是没有发现,后面详细说这个)
那CMFCToolBar呢?
这个有点诡异,他的create(this)的父窗口居然是一个CDockSite的对象,然后这个CDockSite对象的父窗口才是CMainFrame的对象。
原来上面执行过一步DockPane(&m_wndToolBar),这才是罪魁祸首。
如果没有这一步可以直接m_wndReBar.AddBar(this)
这一步是让它有停靠功能
那如果没有这句呢?
所 以你m_wndReBar.AddBar一个CMFCToolBar当然不对了,如果想要把CMFCToolBar添加到CReBar需要 m_wndReBar.AddBar((&m_wndToolBar)->GetParent() ,TEXT("工具"), NULL,RBBS_GRIPPERALWAYS|RBBS_FIXEDBMP|RBBS_USECHEVRON); ,这个就不解释了,你懂的。
这个问题解决了就是CReBar的实现问题了,其实ReBar是SDK的一个窗口类型,CreateWindowEx的时候指定窗口类型为REBARCLASSNAME就可以
首先create一个对象,然后AddBar一个对象,最后配置REBARBANDINFO rbbi,最后设置下这个窗口的位置就OK了
这里的关键在于这个REBARBANDINFO的对象。它设置了加入的子窗口的句柄,“占地面积”,背景图等等一些信息。
我跟踪了AddBar函数,它内部调用了_AddMFCToolBar这个函数,在这个函数里,它先设置了默认的REBARBANDINFO对象
pRBBI->cbSize = m_nReBarBandInfoSize;
pRBBI->fMask |= RBBIM_CHILD | RBBIM_CHILDSIZE;
pRBBI->hwndChild = pBar->m_hWnd;
这个很简单
然后
(BOOL)DefWindowProc(RB_INSERTBAND, (WPARAM)-1, (LPARAM)pRBBI);
发送了这个消息,这应该进行的就是父窗口改变的一些操作,不过我跟踪不下去了,微软好像没有提供代码。
最后刷新了下布局管理器。
CFrameWnd* pFrameWnd = AFXGetParentFrame(this);
if (pFrameWnd != NULL)
pFrameWnd->RecalcLayout();
最后附一个微软提供的用SDK创建CReBar的例子,方便大家理解
http://technet.microsoft.com/zh-cn/library/hh298374
以上的就是我对CMFCToolBar,CToolBar和CReBar的理解。
有什么错误请各位看官指出