首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

輕鬆打造 Visual C++ 風格的停靠視窗界面

     編輯:VC 教學

在開發 Windows 應用程式時,擁有類似 Visual Studio IDE 那樣靈活的停靠視窗界面,能大幅提升使用者體驗。左側的工具箱、底部的輸出視窗,都能自由浮動、調整大小、自動隱藏。本文將詳細介紹如何在 MFC 專案中,利用 CSizingControlBar 衍生類別 CCoolBar,快速實現這類專業級界面,並提供完整原始碼供參考。

一、 核心實現原理

實現這類界面的關鍵在於 CControlBar 架構。我們不必從零開始編寫,國外開發者 Cristi Posea 已經實作了一個功能完善的 CSizingControlBar 類別,支援動態調整大小、浮動、停靠等核心功能。本文作者在此基礎上進行了精簡與封裝,將其重命名為 CCoolBar,使其更易於整合到專案中。

二、 逐步實作範例

1. 專案準備

  • 建立一個名為 BarDemo 的 MFC SDI 專案,其他選項保持預設。
  • 將範例程式碼中的四個檔案 sizecbar.h、sizecbar.cpp、scbarg.h、scbarg.cpp 複製到專案目錄,並透過 Project > Add to Project > Files 加入專案。此時 ClassView 中將出現 CCoolBar 類別。
  • 在 stdafx.h 中加入標頭檔引用:
    #include "sizecbar.h"
    #include "scbarg.h"

2. 開始編碼

2.1 在 CMainFrame 中新增成員變數

CCoolBar m_wndMyBar1; // 左側停靠視窗
CCoolBar m_wndMyBar2; // 底部停靠視窗

2.2 建立控制列

在 CMainFrame::OnCreate 中撰寫建立程式碼,邏輯與建立一般工具列類似:

if (!m_wndMyBar1.Create(_T("我的控制列"), this, 123)) {
    TRACE0("Failed to create mybar ");
    return -1;
}
if (!m_wndMyBar2.Create(_T("我的控制列2"), this, CSize(100,100), TRUE, 124)) {
    TRACE0("Failed to create mybar ");
    return -1;
}

2.3 設定停靠行為

// 設定樣式:工具提示、飛越效果、動態調整大小
m_wndMyBar1.SetBarStyle(m_wndMyBar1.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
m_wndMyBar2.SetBarStyle(m_wndMyBar2.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

// 啟用停靠功能,允許停靠在任意邊緣
m_wndMyBar1.EnableDocking(CBRS_ALIGN_ANY);
m_wndMyBar2.EnableDocking(CBRS_ALIGN_ANY);

// 執行停靠:左側與底部
DockControlBar(&m_wndMyBar1, AFX_IDW_DOCKBAR_LEFT);
DockControlBar(&m_wndMyBar2, AFX_IDW_DOCKBAR_BOTTOM);

2.4 向控制列加入自訂控制項

核心技巧:建立子控制項時,將控制列指標 (&m_wndMyBar1 或 &m_wndMyBar2) 作為父視窗傳入。注意:單一控制列同一時間只能容納一個直接子視窗,若需多頁籤請使用 Tab 控制項。

範例 (1):在底部控制列放入編輯控制項

// CMainFrame 成員變數
CEdit m_wndEdit;

// OnCreate 中建立
m_wndEdit.Create(WS_VSCROLL | WS_CHILD | WS_VISIBLE | ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN,
                 CRect(0,0,0,0), &m_wndMyBar2, 101);
m_wndEdit.ModifyStyleEx(0, WS_EX_CLIENTEDGE);

範例 (2):在左側控制列放入樹狀控制項

// CMainFrame 成員變數
CTreeCtrl m_wndTree;

// 建立樹狀控制項
if (!m_wndTree.Create(WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT,
                      CRect(0,0,0,0), &m_wndMyBar1, 100)) {
    TRACE0("Failed to create tree control");
    return -1;
}
m_wndTree.ModifyStyleEx(0, WS_EX_CLIENTEDGE);

// 填充樹狀節點
HTREEITEM hRoot = m_wndTree.InsertItem(_T("VC 知識庫線上雜誌"));
m_wndTree.InsertItem(_T("電子文檔"));
m_wndTree.InsertItem(_T("線上雜誌第一期"), hRoot);
m_wndTree.InsertItem(_T("線上雜誌第二期"), hRoot);

範例 (3):在控制列中嵌入對話框

  1. 資源編輯器建立 Child 型、無邊框對話框,ID 為 IDD_DIALOGBAR。
  2. 用 ClassWizard 產生對應類別 CVCKBASEDlg。
  3. CMainFrame 新增成員 CVCKBASEDlg m_wndVCKBASE。
  4. 建立並顯示:
    m_wndVCKBASE.Create(IDD_DIALOGBAR, &m_wndMyBar1);
    m_wndVCKBASE.ShowWindow(SW_SHOW);

範例 (4):使用 Tab 控制項實現多頁籤切換 (左側控制列)

範例程式碼提供了封裝類 CCoolTabCtrl,用法如下:

// 建立 Tab 控制項
m_TabCtrl.Create(TCS_DOWN | WS_CHILD | WS_VISIBLE, CRect(0,0,100,100), &m_wndMyBar1, 125);

// 將樹狀控制項作為第一個頁籤頁面 (父視窗指向 m_TabCtrl)
if (!m_wndTree.Create(WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT,
                      CRect(0,0,0,0), &m_TabCtrl, 100)) { ... }

// 加入頁籤頁面
m_TabCtrl.AddPage(&m_wndTree, _T("VC知識庫"), IDI_ICON1);           // 現有視窗
m_TabCtrl.AddPage(RUNTIME_CLASS(CVCKBASEDlg), IDD_DIALOGBAR, _T("第二頁"), IDI_ICON2); // 動態建立對話框
m_TabCtrl.AddPage(RUNTIME_CLASS(CMyDlg), IDD_DIALOGBAR2, _T("第三頁"), IDI_ICON3);
m_TabCtrl.UpdateWindow();

重要: 需動態建立的對話框類別 (CVCKBASEDlg, CMyDlg) 必須加入動態建立巨集:

// .h 檔
DECLARE_DYNCREATE(CVCKBASEDlg)

// .cpp 檔
IMPLEMENT_DYNCREATE(CVCKBASEDlg, CDialog)

三、 進階技巧與常見問題

3.1 保持浮動視窗的專用標題列 (防止變成 ToolWindow)

在 stdafx.h 定義巨集,並在 OnCreate 中 EnableDocking 後設定浮動框架類別:

// stdafx.h
#define _SCB_REPLACE_MINIFRAME

// CMainFrame::OnCreate
#ifdef _SCB_REPLACE_MINIFRAME
m_pFloatingFrameClass = RUNTIME_CLASS(CSCBMiniDockFrameWnd);
#endif

3.2 啟用扁平化風格

在 stdafx.h 加入:#define _SCB_STYLE_FLAT

3.3 讓兩個控制列並排停靠在同一列/行

利用 RecalcLayout 取得第一個控制列位置,稍微偏移後停靠第二個:

// 同一底部列
DockControlBar(&m_wndMyBar1, AFX_IDW_DOCKBAR_BOTTOM);
RecalcLayout();
CRect rect; m_wndMyBar1.GetWindowRect(rect);
rect.OffsetRect(1, 0);
DockControlBar(&m_wndMyBar2, AFX_IDW_DOCKBAR_BOTTOM, rect);

// 同一右側行
DockControlBar(&m_wndMyBar1, AFX_IDW_DOCKBAR_RIGHT);
RecalcLayout();
CRect rect; m_wndMyBar1.GetWindowRect(rect);
rect.OffsetRect(0, 1);
DockControlBar(&m_wndMyBar2, AFX_IDW_DOCKBAR_RIGHT, rect);

編譯執行,即可擁有媲美 VC IDE 的專業停靠視窗界面!感謝 Cristi Posea 提供的優秀基礎類別。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved