您的位置:首页 > 其它

关于CToolBar、CMFCToolBar和CReBar的一些废话

2013-12-10 20:31 225 查看
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的理解。

有什么错误请各位看官指出
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: