靜態控件功能簡單但用途極廣:顯示標籤、分組框、圖標、位圖、分隔線、動畫等。MFC CStatic 封裝文本/圖像顯示、對齊樣式、前綴轉義控制及圖片資源動態加載。本文系統講解全風格、三種顯示模式切換、動態圖片加載代碼模板。
BOOL Create(LPCTSTR lpszText, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID = 0xffff);
| 風格 | 效果 |
|---|---|
SS_LEFT | 左對齊 (默認) |
SS_CENTER | 居中對齊 |
SS_RIGHT | 右對齊 |
SS_NOPREFIX | 禁用 & 加速鍵前綴轉義 (直接顯示 &) |
| 風格 | 顯示內容 | 配置方式 | 典型用途 |
|---|---|---|---|
SS_LEFT/CENTER/RIGHT (無圖像風格) | 文本 | SetWindowText | 標籤、提示、數值顯示 |
SS_BITMAP | 位圖 | SetBitmap(HBITMAP) | Logo、圖片預覽、狀態圖標 |
SS_ICON | 圖標 | SetIcon(HICON) | 應用圖標、文件類型圖標 |
SS_GRAYRECT | 灰色矩形框 | 無需配置 | 分組視覺分隔 |
SS_BLACKRECT | 黑色矩形框 | 無需配置 | 分隔線、邊框 |
SS_WHITERECT | 白色矩形框 | 無需配置 | 背景遮罩 |
SS_ETCHEDHORZ | 蝕刻水平線 | 無需配置 | 3D 分隔線 |
SS_ETCHEDVERT | 蝕刻垂直線 | 無需配置 | 3D 分隔線 |
SS_CENTERIMAGE | 圖像居中顯示 (配合 BITMAP/ICON) | 自動居中,不拉伸 | 固定尺寸框內顯示不同尺寸圖片 |
SS_REALSIZECONTROL | 按實際尺寸顯示 (不拉伸) | 配合 BITMAP/ICON | 保持原始比例 |
SS_SUNKEN | 凹陷邊框 | 配合文本/圖像 | 輸入框風格標籤 |
// 設置文本
m_static.SetWindowText(_T("Hello World"));
// 獲取文本
CString text;
m_static.GetWindowText(text);
// 動態修改對齊 (需重繪)
m_static.ModifyStyle(SS_LEFT, SS_CENTER);
m_static.Invalidate();
// 從資源加載
HICON hIcon = AfxGetApp()->LoadIcon(IDI_MYICON);
m_static.SetIcon(hIcon);
// 獲取當前圖標
HICON hCur = m_static.GetIcon();
// 釋放資源 (若手動 LoadImage)
DestroyIcon(hIcon);
// 動態加載位圖資源並顯示 (完整代碼模板)
void CMyDialog::ShowBitmap(UINT nBitmapID) {
// 1. 確保風格包含 SS_BITMAP | SS_CENTERIMAGE
m_static.ModifyStyle(0, SS_BITMAP | SS_CENTERIMAGE);
// 2. 加載位圖對象
CBitmap bmp;
if (!bmp.LoadBitmap(nBitmapID)) {
AfxMessageBox(_T("位圖加載失敗"));
return;
}
// 3. 設置位圖 (Detach 轉移所有權給靜態控件)
HBITMAP hOld = m_static.SetBitmap(bmp.Detach());
// 4. 釋放舊位圖 (防止內存洩漏)
if (hOld) DeleteObject(hOld);
// 5. 強制重繪
m_static.Invalidate();
}
void LoadBitmapFromFile(LPCTSTR pszPath) {
// 1. 使用 LoadImage 從文件加載
HBITMAP hBmp = (HBITMAP)LoadImage(NULL, pszPath, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if (!hBmp) return;
// 2. 設置並管理生命週期
HBITMAP hOld = m_static.SetBitmap(hBmp);
if (hOld) DeleteObject(hOld);
// 注意:此處 hBmp 所有權已轉移,對話框銷毀時需手動 DeleteObject
// 建議成員變量保存 hBmp,在 OnDestroy 中釋放
}
void CreateDynamicBitmap(int width, int height) {
CClientDC dc(&m_static);
CDC memDC;
memDC.CreateCompatibleDC(&dc);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&dc, width, height);
CBitmap* pOld = memDC.SelectObject(&bmp);
// 在 memDC 上繪圖...
memDC.FillSolidRect(0, 0, width, height, RGB(255,255,255));
memDC.TextOut(10, 10, _T("動態生成"));
memDC.SelectObject(pOld);
// 設置顯示
HBITMAP hOld = m_static.SetBitmap(bmp.Detach());
if (hOld) DeleteObject(hOld);
}
SS_BITMAPSetBitmap 參數為有效 HBITMAPInvalidate() 觸發重繪SS_CENTERIMAGE (居中不拉伸) 或 SS_REALSIZECONTROL (實際尺寸)SetBitmap 返回舊 HBITMAP 必須 DeleteObject;LoadImage 加載的位圖所有權轉移後需在銷毀時釋放ModifyStyle 移除舊風格LR_CREATEDIBSECTION 加載位圖,或改用 CImage/GDI+ 支持縮放rect 或啟用 SS_ENDELLIPSIS (需 WinXP+)class CStatusPanel {
CStatic m_leds[4]; // 紅/黃/綠/藍
CBitmap m_bmpOn[4], m_bmpOff[4];
public:
void Init(CWnd* pParent, UINT baseID) {
for (int i = 0; i < 4; ++i) {
m_leds[i].Create(_T(""), WS_CHILD | WS_VISIBLE | SS_BITMAP | SS_CENTERIMAGE,
CRect(10+i*30, 10, 35+i*30, 35), pParent, baseID+i);
m_bmpOn[i].LoadBitmap(IDB_LED_RED_ON + i);
m_bmpOff[i].LoadBitmap(IDB_LED_RED_OFF + i);
SetLed(i, FALSE);
}
}
void SetLed(int index, BOOL on) {
m_leds[index].SetBitmap((on ? m_bmpOn[index] : m_bmpOff[index]).Detach());
m_leds[index].Invalidate();
}
};
本文整理自 MFC 經典技術文檔,適用於 VC6~VS2022 所有版本。