MFC CStatusBar 預設僅支援文字面板。若需在狀態條顯示圖示 (如連線狀態燈號、動畫圖示),必須實作 Owner-Draw 機制。本文示範完整步驟:建立位圖資源、擴充指示器陣列、衍生 CBitmapStatusBar 並覆寫繪圖虛擬函數,相容 MFC 4.0 以上版本。
資源編輯器新增位圖,ID 設為 IDB_BITMAP1。
在 MainFrm.cpp:
static UINT indicators[] =
{
ID_SEPARATOR,
ID_INDICATOR_BITMAP, // 新增位圖面板
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
BitmapStatusBar.h:
class CBitmapStatusBar : public CStatusBar
{
public:
#if _MFC_VER >= 0x400
virtual void DoPaint(CDC* pDC);
#else
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
#endif
};
BitmapStatusBar.cpp - MFC 4.0+ 版本:
void CBitmapStatusBar::DoPaint(CDC* pDC)
{
CRect rect;
GetItemRect(1, &rect); // 取得第 1 個面板矩形
pDC->ExcludeClipRect(&rect); // 排除該區域,讓基底類別繪製其餘部分
CStatusBar::DoPaint(pDC); // 繪製其他面板
CRgn rgn;
rgn.CreateRectRgnIndirect(&rect);
pDC->SelectClipRgn(&rgn); // 限制繪製區域僅在面板內
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1); // 載入位圖
CDC srcDC;
srcDC.CreateCompatibleDC(NULL);
CBitmap* pOldBmp = srcDC.SelectObject(&bmp);
pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(),
&srcDC, 0, 0, SRCCOPY);
srcDC.SelectObject(pOldBmp);
bmp.DeleteObject();
}
MFC 4.0 前版本 (DrawItem) 同理,使用 LPDRAWITEMSTRUCT 提供的 hDC 與 rcItem。
MainFrm.h:
// CStatusBar m_wndStatusBar;
CBitmapStatusBar m_wndStatusBar;
MainFrm.cpp OnCreate 中:
#if _MFC_VER >= 0x400
UINT nID, nStyle;
int cxWidth;
m_wndStatusBar.GetPaneInfo(1, nID, nStyle, cxWidth);
m_wndStatusBar.SetPaneInfo(1, nID, nStyle | SBT_OWNERDRAW, cxWidth);
#endif
_MFC_VER 區分 DoPaint (MFC 4.0+) 與 DrawItem (舊版)。ExcludeClipRect + SelectClipRgn 確保位圖僅繪製於指定面板。SelectObject 後須還原舊位圖並 DeleteObject,避免 GDI 物件洩漏。編譯執行後,狀態條第二個面板將顯示 IDB_BITMAP1 位圖,隨視窗大小自動調整,並與其他文字面板共存。