MFC CToolBar 僅支援單行文字。本文實現 CMTToolBar 類別,核心技術是「將多行文字渲染為位圖,替換原工具列位圖」,支援工具列資源中以 \n 分隔多行文字。
RT_TOOLBAR) 取得按鈕資訊與原始圖片尺寸\n 分割多行,計算最大行數、單字高度、最大寬度SetSizes 更新按鈕尺寸,AddReplaceBitmap 替換工具列位圖BOOL CMTToolBar::ShowText(UINT nIDResource) {
// 1. 讀取資源取得原始尺寸
CToolBarData* pData = (CToolBarData*)LockResource(hGlobal);
CSize sizeImage(pData->wWidth, pData->wHeight);
// 2. 解析多行文字
CStringArray* pstrArray = new CStringArray[nCount];
int nLines = 0, nCharHeight = 0;
for (int i = 0; i < nCount; ++i) {
// 略過分隔器...
CString strT; strT.LoadString(tb.idCommand);
int nPos = strT.Find('\n') + 1;
while (nPos > 0) {
// 分割各行存入 pstrArray[nBtnCount]
nLines = max(nLines, nIndex+1);
nCharHeight = max(size.cy, nCharHeight);
}
}
// 3. 計算新尺寸
CSize sizeNewImage(sizeImage.cx, nLines * nCharHeight);
// 4. 繪製新位圖
dcDst.FillSolidRect(..., ::GetSysColor(COLOR_BTNFACE));
for (i = 0; i < nBtnCount; ++i) {
dcDst.BitBlt(i*sizeNewImage.cx + nStartX, 0, sizeImage.cx, sizeImage.cy, &dcSrc, ...);
for (j = 0; j < pstrArray[i].GetSize(); j++) {
dcDst.TextOut(i*sizeNewImage.cx + nStratX, sizeImage.cy + j*nCharHeight, ...);
}
}
// 5. 套用
SetSizes(sizeNewImage + CSize(7,7), sizeNewImage);
AddReplaceBitmap((HBITMAP)bmpDst.Detach());
return TRUE;
}
第一行\n第二行\n第三行CMTToolBarOnCreate 中呼叫:m_wndToolBar.ShowText(IDR_MAINFRAME);| 特點 | 限制 |
|---|---|
| 支援任意行數文字 | 文字渲染為位圖,無法動態改變字型大小/樣式 |
| 自動計算最佳按鈕寬度 | 高 DPI 環境下位圖可能模糊 |
| 文字垂直/水平置中對齊 | 不支援 RTL 語言 |
| 保留原始圖示完整顯示 | 按鈕寬度由最長文字決定,可能過寬 |
CCustomDraw 即時繪製文字(不生成位圖)CImageList 支援高 DPI 圖示CMTToolBar 以「文字轉位圖」巧妙繞過 MFC 工具列單行限制,程式碼約 150 行,邏輯清晰。適合按鈕文字固定、不需頻繁動態變更的場景。原始碼可直接整合專案使用。