|
4.1 工具条的可视化设计 从4.0版开始,Visual C++支持一种新型的工具条资源,这使得工具条的创建比以往更加方便灵活了。在MFC中,工具条的功能由类CToolBar实现。工具条资源和工具条类CToolBar是工具条的两个要素。创建工具条的基本步骤是:
使用缺省配置时,AppWizard会自动创建一个工具条。如图4.1所示,这个工具条包含一些常用按钮,如打开文件、存盘、打印等等。用户可以修改这个工具条,去掉无用的按钮,加入自己需要的按钮。如果用户需要创建两个以上的工具条,则不能完全依赖AppWizard,需要自己手工创建之。本节将分别讨论这两种方法。 4.1.1利用AppWizard自动创建 自动创建工具条很简单,请读者按以下步骤操作:
完成以上操作后,工程Record被创建并被自动载入Developer Studio中。将项目工作区切换到资源视图,并展开资源,就会发现其中有一个名为IDR_MAINFRAME的Toolbar(工具条)资源。用鼠标双击“IDR_MAINFRAME”,Developer Studio会打开一个功能强大的工具条资源编辑窗口,如图4.2所示。该窗口的上部显示出了工具条上的按钮,当用户用鼠标选择某一按钮时,在窗口的下部会显示该按钮的位图。在窗口旁边有一个绘图工具面板和一个颜色面板,供用户编辑按钮位图时使用。
图4.2 工具条资源编辑窗口
在修改工具条以前,首先要修改菜单资源。请按以下几步修改菜单资源:
修改后的菜单如图4.3所示。
图4.3 修改后的菜单 接下来的任务是修改工具条资源,具体步骤是:
修改完后,读者可以编译并运行Record,来看看修改的结果。读者很快会注意到Start和Stop菜单项及按钮都是灰色的。这个现象是正常的,其原因将在4.2节解释。有趣的是工具条可以被拖动(请在工具条的空白地方拖动)并停泊在主框架窗口的任何其它边上,并且工具条是可以浮动的,即当用鼠标双击工具条的空白处时,工具条变成了一个浮动窗口,可被拖动到屏幕上的任意地方。这些有趣的现象将在4.2节解释。不管怎么说,创建和修改工具条的任务已经完成了。 4.1.2手工创建 如果想要再加一个工具条,那么AppWizard就无能为力了,必须手工创建。假设Record程序的声音采样频率有11KHZ和44KHZ两档选择,现在我们的任务是再创建一个工具条,可让用户对这两种档次进行选择。本来这样的功能应该位于第一个工具条内,但为了演示工具条的手工创建,这里不妨来个多此一举。 如果Record工程不在Developer Studio中,请选择命令File->Open Workspace打开Record工程。首先要对原来的菜单进行修改,步骤如下:
表4.1 菜单项的属性
接着要创建一个新的工具条资源,请按以下步骤进行:
要把这个新设计的工具条加入到程序中,需要在程序中加入一些与创建有关的源代码。在创建第一个工具条时,AppWizard在程序中自动加入了创建源代码,通过仿制这些代码,我们很容易创建出第二个工具条。 在MFC中,工具条的功能由类CToolBar实现。工具条实际上是主框架窗口的子窗口,因此工具条对象应该依附于主框架窗口对象。在AppWizard创建的MFC程序中,主框架窗口的类名是CMainFrame,该类是MFC标准类CFrameWnd类的派生类。将项目工作区切换至类视图并展开CMainFrame类,读者会发现该类有一个名为m_wndToolbar的成员。双击该成员,则Developer Studio会自动打开类CMainFrame所在的头文件,并将光标停在对m_wndToolbar成员的定义处。
对m_wndToolBar的定义如下: CToolBar m_wndToolBar; 由此可见m_wndToolBar是一个CToolBar对象,它是CMainFrame的成员。现在请紧接着该成员加入一个新的成员: CToolBar m_wndToolBar1; m_wndToolBar1代表第二个工具条。读者不要以为给CMainFrame加入一个CToolBar对象就完事了。实际的创建工具条的工作不会在构造CToolBar对象时完成,只有调用了类CToolBar的一些成员函数后,创建工作才能结束。 对工具条的实际创建工作在CMainFrame::OnCreate函数中完成。OnCreate函数是在创建窗口时被调用的,这时窗口的创建已部分完成,窗口对象的m_hWnd成员中存放的HWND句柄也已有效,但窗口还是不可见的。因此一般在OnCreate函数中作一些诸如创建子窗口的初始化工作。
找到CMainFrame::OnCreate函数,对该函数进行一些修改,修改的部分如清单4.1的黑体字所示。在以后,凡是程序中手工修改的部分,一般都会用黑体显示。 清单4.1 修改后的CMainFrame::OnCreate函数 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
if (!m_wndToolBar.Create(this) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create }
if (!m_wndToolBar1.Create(this) || !m_wndToolBar1.LoadToolBar(IDR_TOOLBAR1)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create }
if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create }
// TODO: Remove this if you don't want tool tips or a resizeable toolbar m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
// TODO: Delete these three lines if you don't want the toolbar to // be dockable m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
m_wndToolBar1.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);
DockControlBar(&m_wndToolBar1); return 0; } 注意在CMainFrame::OnCreate函数首先调用了CFrameWnd::OnCreate。这行代码是AppWizard自动加入的,但有必要解释一下。CMainFrame是CFrameWnd类的继承类,在CMainFrame::OnCreate中首先要调用基类CFrameWnd的OnCreate函数,因为基类也要进行一些初始化工作,而基类的OnCreate函数不会自动调用,因此需要在继承类的OnCreate函数中显式调用。OnCreate实际上是WM_CREATE消息的消息处理函数,读者可能要问,为什么是派生类的OnCreate处理WM_CREATE消息,而不是基类的OnCreate呢。如果读者仔细观察OnCreate函数在CMainFrame类头文件中的说明,就会发现在该函数前有一个afx_msg前缀。afx_msg的作用与virtual关键字类似,它使得被说明的函数有虚拟函数的特性,即由继承类而不是基类的处理函数来处理消息。 读者可以看出黑体的代码是仿照第一个工具条的创建代码进行编写的。事实上,笔者不过是将原来的代码复制一份,然后在略作修改而已。
对第二个工具条的创建代码的解释是:首先,调用CToolBar::Create以创建工具条窗口,注意Create函数的参数是this指针,这是因为主框架窗口是工具条的父窗口。接着调用CToolbar::LoadToolBar(IDR_TOOLBAR1)以载入工具条资源。然后调用CToolBar::SetBarStyle指定工具条的风格,在调用该函数时先调用CToolBar::GetBarStyle取得工具条的风格,然后在原有风格的基础上又指定了CBRS_TOOLTIPS、 CBRS_FLYBY和CBRS_SIZE_DYNAMIC风格,这使得工具条可显示工具提示,并可以动态改变尺寸。接着调用CToolBar::EnableDocking(CBRS_ALIGN_ANY)使工具条是可以停泊的,但还需调用CFrameWnd::EnableDocking(CBRS_ALIGN_ANY),只有这样才能实现可停泊的工具条。最后调用CFrameWnd::DockControlBar以停泊工具条。 编译并运行Record看看,现在Record程序已经拥有两个工具条了。至此创建工具条的任务已经完成,下面需要对工具条编程,以使其能够发挥执行命令的功能。
作者: 不详, 来源: Visual C++王朝 |