Windows 應用程序的控制欄包括工具欄和狀態欄等。在工具欄中可以添加按鈕和控件,實現快捷操作。在狀態欄中可以顯示一些提示信息。MFC 中,控制欄中的工具欄和狀態欄分別通過 CToolBar 類和 CstatusBar 類實現,它們的父類都為 CContorlBar 類。
創建工具欄,首先創建一個工具欄資源,然後構造一個 CToolBar 類對象,接下來調用 CToolBar::CreateEx 函數創建工具欄窗口,最後調用 CToolBar::LoadToolBar 函數加載工具欄資源。
//創建1個多文檔的應用程序,添加1個工具欄資源,ID為IDR_TOOLBAR,在CMainFrame類中添加成員變量 public: CToolBar m_wndDemoToolBar; //在CMainFrame類中添加WM_CREATE消息處理函數 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; //... //創建工具欄窗口 if (!m_wndDemoToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC)) { return -1; } //加載工具欄資源 if (!m_wndDemoToolBar.LoadToolBar(IDR_TOOLBAR)) { return -1; } return 0; }
設置工具欄的標題可以調用CWnd::SetWindowText函數。
//在CMainFrame類中添加WM_CREATE消息處理函數 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } //設置工具欄標題 CString strText = _T(""); strText.LoadString(AFX_IDS_APP_TITLE); m_wndToolBar.SetWindowText(strText); //... return 0; }
停靠工具欄,首先調用CControlBar::EnableDocking函數和CFrameWnd::EnableDocking函數,然後調用CFrameWnd::DockControlBar函數。
//創建1個多文檔的應用程序,添加1個工具欄資源,ID為IDR_TOOLBAR,在CMainFrame類中添加成員變量 public: CToolBar m_wndDemoToolBar; //在CMainFrame類中添加DockBar成員函數 void CMainFrame::DockBar(CControlBar* pDestBar, CControlBar* pSrcBar) { RecalcLayout(TRUE); //獲得工具欄窗口坐標 CRect rect; pDestBar->GetWindowRect(&rect); rect.OffsetRect(1, 0); //獲得工具欄風格 DWORD dwStyle = pDestBar->GetBarStyle(); UINT nDockBarID = 0; if (dwStyle & CBRS_ALIGN_TOP) { nDockBarID = AFX_IDW_DOCKBAR_TOP; } else if (dwStyle & CBRS_ALIGN_BOTTOM) { nDockBarID = AFX_IDW_DOCKBAR_BOTTOM; } else if (dwStyle & CBRS_ALIGN_LEFT) { nDockBarID = AFX_IDW_DOCKBAR_LEFT; } else if (dwStyle & CBRS_ALIGN_RIGHT) { nDockBarID = AFX_IDW_DOCKBAR_RIGHT; } //停靠工具欄 DockControlBar(pSrcBar, nDockBarID, &rect); } //在CMainFrame類中添加WM_CREATE消息處理函數 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; //... //創建工具欄窗口 if (!m_wndDemoToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC)) { return -1; } //加載工具欄資源 if (!m_wndDemoToolBar.LoadToolBar(IDR_TOOLBAR)) { return -1; } return 0; }
設置工具欄的位圖可以調用CToolBar::SetBitmap函數。
//創建1個多文檔的應用程序,添加1個工具欄資源,ID為IDR_TOOLBAR,添加1個位圖資源,ID為IDB_BITMAP1,在CMainFrame類中添加成員變量 public: CToolBar m_wndDemoToolBar; CBitmap m_Bitmap; //在CMainFrame類中添加WM_CREATE消息處理函數 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; //... //創建工具欄窗口 if (!m_wndDemoToolBar.CreateEx(this,TBSTYLE_FLAT,WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC)) { return -1; } //加載工具欄資源 if (!m_wndDemoToolBar.LoadToolBar(IDR_TOOLBAR)) { return -1; } //停靠工具欄 m_wndDemoToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockBar(&m_wndToolBar,&m_wndDemoToolBar); //設置位圖 m_Bitmap.LoadBitmap(IDB_BITMAP1); m_wndDemoToolBar.SetBitmap((HBITMAP)m_Bitmap); return 0; }
為工具欄按鈕添加文本標簽可以調用CToolBar::SetButtonText函數。
//創建1個多文檔的應用程序,在CMainFrame類中添加WM_CREATE消息處理函數 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } for (int n = 0;n < m_wndToolBar.GetCount();n++) { //獲得工具欄按鈕ID UINT nID = m_wndToolBar.GetItemID(n); CString strText = _T(""); if (!strText.LoadString(nID)) { continue; } int nIndex = strText.Find(_T('\n')); if (nIndex < 0) { continue; } strText = strText.Right(strText.GetLength() - nIndex - 1); //設置工具欄按鈕文本 m_wndToolBar.SetButtonText(n,strText); } CRect rect; m_wndToolBar.GetItemRect(0,&rect); //設置工具欄按鈕尺寸 m_wndToolBar.SetSizes(rect.Size(),CSize(16,15)); //... return 0; }
為工具欄按鈕添加下拉箭頭,首先調用CToolBarCtrl::SetExtendedStyle函數,設置工具欄的TBSTYLE_EX_DRAWDDARROWS風格;然後調用CToolBar::SetButtonStyle函數,在每一個添加下拉箭頭的按鈕上設置TBSTYLE_DROPDOWN風格。
//創建1個多文檔的應用程序,在CMainFrame類中添加WM_CREATE消息處理函數 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } //設置工具欄擴展風格 m_wndToolBar.GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS); //設置工具欄按鈕風格 int nIndex = m_wndToolBar.CommandToIndex(ID_FILE_NEW); UINT nStyle = m_wndToolBar.GetButtonStyle(nIndex); nStyle |= TBSTYLE_DROPDOWN; m_wndToolBar.SetButtonStyle(nIndex, nStyle); //... return 0; } //在CMainFrame類中為工具欄添加TBN_DROPDOWN消息處理函數 //在MainFrame.h頭文件中加入消息處理函數的聲明: afx_msg void OnDropDownToolBar(NMHDR* pNMHDR, LRESULT* pResult); //在MainFrame.cpp中加入下拉箭頭的TBN_DROPDOWN消息映射: BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) //{{AFX_MSG_MAP(CMainFrame) ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnDropDownToolBar) //}}AFX_MSG_MAP END_MESSAGE_MAP() //TBN_DROPDOWN消息的實現: void CMainFrame::OnDropDownToolBar(NMHDR* pNMHDR, LRESULT* pResult) { NMTOOLBAR* pNMToolBar = (NMTOOLBAR*)pNMHDR; switch(pNMToolBar->iItem) { case ID_FILE_NEW: ::AfxMessageBox(_T("新建")); break; default: break; } }
默認情況下,AppWizard使用工具欄資源來設置按鈕的圖像。工具欄資源包含一個復合的位圖,該位圖在調用CToolbar::LoadToolBar函數時將被轉換成一個圖像列表。
為工具欄按鈕設置熱點圖像,應該首先調用CImageList::Create函數創建一個新的圖像列表;然後調用CToolBarCtrl::SetHotImageList函數,將該圖像列表設置為工具欄的熱點圖像列表。
//創建1個多文檔的應用程序,在CMainFrame類中添加成員變量和WM_CREATE消息處理函數 private: CImageList m_ImageList; int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } //創建圖像列表 if (!m_ImageList.Create(IDB_BITMAP1,16,0,RGB(128,128,128))) { return -1; } //設置工具欄圖像列表 m_wndToolBar.GetToolBarCtrl().SetHotImageList(&m_ImageList); //... return 0; }
啟用和禁用工具欄的工具提示,可以通過調用CControlBar::SetBarStyle函數,添加或刪除CBRS_TOOLTIPS風格實現。
//創建1個多文檔的應用程序,分別在IDR_MAINFRAME和IDR_DEMOTYPE菜單資源中添加1個子菜單,在子菜單中添加1個菜單項(ID:ID_ENABLE_TOOLTIPS) //在CMainFrame類中為菜單項添加命令處理函數 void CMainFrame::OnEnableTooltips() { //獲得工具欄風格 DWORD dwStyle = m_wndToolBar.GetBarStyle(); //啟用或禁用工具提示 if (dwStyle & CBRS_TOOLTIPS) { dwStyle &= ~CBRS_TOOLTIPS; } else { dwStyle |= CBRS_TOOLTIPS; } //設置工具欄風格 m_wndToolBar.SetBarStyle(dwStyle); } void CMainFrame::OnUpdateEnableTooltips(CCmdUI* pCmdUI) { //獲得工具欄風格 DWORD dwStyle = m_wndToolBar.GetBarStyle(); if (dwStyle & CBRS_TOOLTIPS) { pCmdUI->SetCheck(TRUE); } else { pCmdUI->SetCheck(FALSE); } }
在工具欄中添加組合框,應該首先調用CToolBar::SetButtonInfo函數,為組合框創建一個空白區域(TBBS_SEPARATOR), 然後調用CToolBar::GetItemRect函數,獲得空白區域的大小和位置,最後調用CComboBox::Create函數,在空白區域創建組合框。
//創建1個多文檔的應用程序,在CMainFrame類中添加成員變量 CComboBox m_ComboBox; //在CMainFrame類中添加CreateComboBox成員函數 BOOL CMainFrame::CreateComboBox(UINT nID) { int nIndex = 0; CRect rect; //查找按鈕 while (m_wndToolBar.GetItemID(nIndex) != nID) { nIndex++; } //為組合框創建一個空白區域 m_wndToolBar.SetButtonInfo(nIndex, nID, TBBS_SEPARATOR, 80); //獲得空白區域大小和位置 m_wndToolBar.GetItemRect(nIndex, &rect); //組合框大小和位置 rect.top += 0; rect.bottom += 200; //在空白區域創建組合框 if (!m_ComboBox.Create(WS_CHILD | WS_VISIBLE | CBS_AUTOHSCROLL | CBS_DROPDOWNLIST | CBS_HASSTRINGS, rect, &m_wndToolBar, nID)) { TRACE0("Failed to create combo-box\n"); return FALSE; } //顯示組合框 m_ComboBox.ShowWindow(SW_SHOW); //在組合框中添加字符串 m_ComboBox.AddString("500%"); m_ComboBox.AddString("200%"); m_ComboBox.AddString("150%"); m_ComboBox.AddString("100%"); m_ComboBox.AddString("75%"); m_ComboBox.AddString("50%"); m_ComboBox.AddString("25%"); m_ComboBox.AddString("10%"); m_ComboBox.SetCurSel(3); return TRUE; } //在CMainFrame類中添加WM_CREATE消息才處理函數 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } //創建組合框 if (!CreateComboBox(ID_COMBOBOX)) { TRACE0("Failed to create combo box\n"); return -1; } //... return 0; } //在CMainFrame類中為組合框添加CBN_SELCHANGE消息處理函數 void CMainFrame::OnSelchangeCombobox() { CString strText = _T(""); m_ComboBox.GetWindowText(strText); AfxMessageBox(strText); }
創建狀態欄,首先構造一個CStatusBar類對象,然後調用CStatusBar::Create函數創建狀態欄窗口,最後調用CStatusBar::SetIndicators函數設置狀態欄指示器。
//創建1個多文檔的應用程序,在CMainFrame類中添加成員變量 protected: CStatusBar m_wndDemoStatusBar; //在CMainFrame類中添加WM_CREATE消息處理函數 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; //... //創建狀態欄窗口 if (!m_wndDemoStatusBar.Create(this)) { return -1; } //ID數組 UINT IDArray[2]; for (int n = 0; n < 2; n++) { IDArray[n] = 10000 + n; } //設置狀態欄指示器 m_wndDemoStatusBar.SetIndicators(IDArray, sizeof(IDArray) / sizeof(UINT)); //設置窗格寬度 m_wndDemoStatusBar.SetPaneInfo(0, IDArray[0], SBPS_NORMAL, 100); m_wndDemoStatusBar.SetPaneInfo(1, IDArray[1], SBPS_STRETCH, 0); //設置窗格文本 m_wndDemoStatusBar.SetPaneText(0, _T("狀態欄:")); m_wndDemoStatusBar.SetPaneText(1, _T("")); return 0; }
在狀態欄中添加進度條,應該首先調用CProgressCtrl::Create函數,創建進度條,然後調用CStatusBar::GetItemRect函數,獲得指示器大小和位置,最後調用CWnd::MoveWindow函數移動進度條窗口。
//創建1個多文檔的應用程序,添加1個基類為CStatusBar的類CProgressStatusBar //在CProgressStatusBar類中添加成員變量 public: CProgressCtrl m_Progress; //在CProgressStatusBar類中添加WM_CREATE和WM_SIZE消息處理函數 int CProgressStatusBar::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CStatusBar::OnCreate(lpCreateStruct) == -1) return -1; //創建進度條 m_Progress.Create(WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this, 1); return 0; } void CProgressStatusBar::OnSize(UINT nType, int cx, int cy) { CStatusBar::OnSize(nType, cx, cy); //獲得指示器大小和位置 CRect rect; GetItemRect(0, &rect); //移動進度條窗口 m_Progress.MoveWindow(rect.left + 1, rect.top, rect.Width() - 2, rect.Height()); } //在CMainFrame類中添加成員變量 protected: CProgressStatusBar m_wndProgressStatusBar; //在CMainframe類中添加WM_CREATE消息處理函數 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; //... //創建狀態欄窗口 if (!m_wndProgressStatusBar.Create(this)) { return -1; } //ID數組 UINT IDArray[2]; for (int n = 0; n < 2; n++) { IDArray[n] = 10000 + n; } //設置狀態欄指示器 m_wndProgressStatusBar.SetIndicators(IDArray, sizeof(IDArray) / sizeof(UINT)); //設置窗格寬度 m_wndProgressStatusBar.SetPaneInfo(0, IDArray[0], SBPS_NORMAL, 200); m_wndProgressStatusBar.SetPaneInfo(1, IDArray[1], SBPS_STRETCH, 0); //設置窗格文本 m_wndProgressStatusBar.SetPaneText(0, _T("")); m_wndProgressStatusBar.SetPaneText(1, _T("")); //設置進度條 m_wndProgressStatusBar.m_Progress.SetRange(0, 100); m_wndProgressStatusBar.m_Progress.SetStep(10); m_wndProgressStatusBar.m_Progress.SetPos(50); return 0; }
顯示或隱藏工具欄和狀態欄,可以調用CFrameWnd::ShowControlBar函數。
//創建1個多文檔的應用程序,分別在IDR_MAINFRAME和IDR_DEMOTYPE菜單資源中添加1個子菜單,在子菜單中添加2個菜單項(顯示工具欄:ID_SHOW_TOOLBAR,顯示狀態欄:ID_SHOW_STATUSBAR) void CMainFrame::OnShowToolbar() { if (m_wndToolBar.GetStyle() & WS_VISIBLE) { //隱藏工具欄 ShowControlBar(&m_wndToolBar, FALSE, FALSE); } else { //顯示工具欄 ShowControlBar(&m_wndToolBar, TRUE, FALSE); } } void CMainFrame::OnUpdateShowToolbar(CCmdUI* pCmdUI) { if (m_wndToolBar.GetStyle() & WS_VISIBLE) { pCmdUI->SetCheck(TRUE); } else { pCmdUI->SetCheck(FALSE); } } void CMainFrame::OnShowStatusbar() { if (m_wndStatusBar.GetStyle() & WS_VISIBLE) { //隱藏狀態欄 ShowControlBar(&m_wndStatusBar, FALSE, FALSE); } else { //顯示狀態欄 ShowControlBar(&m_wndStatusBar, TRUE, FALSE); } } void CMainFrame::OnUpdateShowStatusbar(CCmdUI* pCmdUI) { if (m_wndStatusBar.GetStyle() & WS_VISIBLE) { pCmdUI->SetCheck(TRUE); } else { pCmdUI->SetCheck(FALSE); } }
首先調用 CReBar::Create 函數創建組合欄,然後調用 CReBar::AddBar 函數在組合欄中添加帶區。
//在resource.h頭文件中添加宏定義 #define IDC_COMBOBOX 1000 #define IDC_TEST 1001 //在CMainFrame類中添加成員變量 protected: CReBar m_wndReBar; CComboBox m_ComboBox; CButton m_Button; //在CMainFrame類中添加WM_CREATE消息處理函數 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; //... //創建組合框 if (!m_ComboBox.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_DROPDOWN, CRect(0, 0, 100, 200), this, IDC_COMBOBOX)) { return FALSE; } //創建按鈕 m_Button.Create(_T("確定"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, CRect(0, 0, 50, 20), this, IDC_TEST); //創建Rebar if (!m_wndReBar.Create(this)) { return -1; } //添加工具欄、組合框、按鈕添加到Rebar中 m_wndReBar.AddBar(&m_wndToolBar); m_wndReBar.AddBar(&m_ComboBox, NULL, NULL, RBBS_NOGRIPPER | RBBS_BREAK); m_wndReBar.AddBar(&m_Button, NULL, NULL, RBBS_NOGRIPPER); return 0; } //在CMainFrame類中為Button控件添加BN_CLICKED消息處理函數 void CMainFrame::OnTest() { CString strText = _T(""); m_ComboBox.GetWindowText(strText); if ((!strText.IsEmpty()) && (CB_ERR == m_ComboBox.FindString(-1, strText))) { m_ComboBox.AddString(strText); } AfxMessageBox(strText); }