
| 出版日期:2001-09-17 总期号:1055 本年期号:70 |
|
把选单加到工具栏
薛瑛 Windows以其良好的用户界面深受广大用户的喜爱,尤其是其IE4的推出增加了新颖的控制。选单栏就是其中一项,它结合了以往的选单和工具栏的特性,如果能将选单放置在工具栏上,既能响应选单消息又能随意拖动,那该多好! 由于在MFC类库中并没有提供CMenuBar类,用户不能像制作工具条那样定制选单栏,这给不少的开发人员带来了不便。本文提供了一种简单快速的方法很好地实现了选单栏的功能。 按钮是工具条的组成元素,它能够响应用户的点击,相应地进行处理。我们就利用这一特性来实现选单控制(如图所示)。程序的开发环境是VC++ 6.0,Windows 98/2000/NT。 新建工程 首先在Visual Studio中选择NEW生成新的工程,我们选择单文档界面SDI。在资源编辑器中生成自己的选单,ID号为IDR_TOOL_MENU。接下来生成自己的工具栏。在主界面窗口MainFrame.h中加入工具栏定义: class CMainFrame : public CFrameWnd {... Protected: CToolBar m_wndMenuBar; ... } 在MainFrame.cpp的类CmainFrame::OnCreate()函数中加入生成代码: int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndMenuBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY| CBRS_SIZE_DYNAMIC )) { TRACE0("Failed to create Menubar\n"); return -1; // fail to create } m_wndMenuBar.SetSizes(CSize(30,20),CSize(1,1));//设置工具栏按钮的大小 …… 添加按钮及响应程序 工具栏生成后,下一步我们就要在工具栏中加入按钮。按钮的数量是根据选单项的多少来决定的。 TBBUTTON button; CString strItem; CMenu mTopMenu; mTopMenu.LoadMenu(IDR_TOOL_MENU); UINT iPos; for (iPos = 0; iPos < mTopMenu.GetMenuItemCount(); iPos++) { mTopMenu.GetMenuString(iPos, strItem, MF_BYPOSITION); button.idCommand = iPos+1; button.iBitmap = -1; button.fsState = 0; button.fsStyle = TBSTYLE_BUTTON; button.iString = -1; m_wndMenuBar.GetToolBarCtrl().InsertButton(iPos,&&button); m_wndMenuBar.SetButtonText(iPos,strItem); } 这里,我们用到了结构TBBUTTON,它定义了按钮的一些特性。其中最重要的是idCommand属性,它定义了按钮的ID命令号,用于在按钮按下时触发ON_ONCOMMAND 命令,我们将其定义成选单项的索引号(Index),fsStyle为按钮的风格,fsState为按钮的状态。通过调用GetToolBarCtrl获得ToolBar的Control类。此类提供了工具栏的通用控制。利用CtoolBarCtrl类可将按钮加入到工具栏中,用SetButtonText可设置按钮的显示文本。下面我们将编写处理按钮命令,以实现我们的选单控制。首先定义消息响应函数OnMenu(),代码如下: MainFrame.h CmainFrame::Public CframeWnd {... protected: //{{AFX_MSG(CMainFrame) afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG afx_msg void OnMenu(UINT nID); DECLARE_MESSAGE_MAP() ... } 在MainFrame.cpp 中加入如下代码: #define MAX_MENU_SUBMENUS 20 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) //{{AFX_MSG_MAP(CMainFrame) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code ! ON_WM_CREATE() //}}AFX_MSG_MAP ON_COMMAND_RANGE(1,MAX_MENU_SUBMENUS, OnMenu) END_MESSAGE_MAP() 其中,ON_COMMAND_RANGE宏将按钮事件的消息ID映射到相应的OnMenu(uID)函数上。再利用OnMenu(uID)函数来进行选单控制。 void CMainFrame::OnMenu(UINT nID) { CMenu m_mnuTopMenu; CRect rWindow,rButton; m_mnuTopMenu.LoadMenu(IDR_MAINFRAME); UINT iPos; for (iPos = 0; iPos < m_mnuTopMenu.GetMenuItemCount(); iPos++) { if (iPos == nID-1) { m_wndMenuBar.GetWindowRect(&&rWindow); m_wndMenuBar.GetItemRect( iPos, &&rButton); rWindow.top += rButton.bottom; rWindow.left += rButton.left; m_wndMenuBar.GetToolBarCtrl().SetState(iPos+1,TBSTATE_PRESSED|TBSTATE_ENABLED); // show popup menu m_mnuTopMenu.GetSubMenu(iPos)-> TrackPopupMenu( TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL, rWindow.left,rWindow.top,this); m_wndMenuBar.GetToolBarCtrl().SetState(iPos+1,TBSTATE_ENABLED); break; } } } OnMenu()函数用按钮的ID号作为参数,首先判断发出命令的是哪一个按钮,计算出响应的选单项及显示位置,用CtoolBarCtrl类的SetState()设置按钮的状态,并调用Cmenu类的TrackPopupMenu()显示选单项。最后我们加入实现选单栏的任意拖放的程序代码: m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&&m_wndMenuBar); 本文所用方法简单、实用,用户可定制OnMenu()函数以实现更多的功能。
通过工具栏中的按钮可以直接调出打印界面 |
|||||||||||||||||