標準 CListBox 垂直捲軸會自動出現/隱藏並調整大小,但**水平捲軸不會自動管理**。當加入超寬字串或垂直捲軸出現壓縮客戶區寬度時,水平捲軸不自動出現,導致內容被截斷無法檢視。
CDJListBox 覆寫關鍵函式
class CDJListBox : public CListBox {
int m_nMaxExtent; // 追蹤最大字串像素寬度
CFont* m_pFont; // 當前字型指標 (為了應對字型變更)
// ...
};
AddString/InsertString/DeleteString/ResetContent
int CDJListBox::AddString(LPCTSTR lpszItem) {
int nResult = CListBox::AddString(lpszItem);
if (nResult >= 0) UpdateHorizontalExtent(lpszItem);
return nResult;
}
int CDJListBox::InsertString(int nIndex, LPCTSTR lpszItem) {
int nResult = CListBox::InsertString(nIndex, lpszItem);
if (nResult >= 0) UpdateHorizontalExtent(lpszItem);
return nResult;
}
void CDJListBox::DeleteString(UINT nIndex) {
CString str;
GetText(nIndex, str); // 刪除前取得文字
CListBox::DeleteString(nIndex);
// 刪除可能是最寬字串,需重新掃描全表
RecalcHorizontalExtent();
}
void CDJListBox::ResetContent() {
CListBox::ResetContent();
m_nMaxExtent = 0;
SetHorizontalExtent(0);
}
UpdateHorizontalExtent
void CDJListBox::UpdateHorizontalExtent(LPCTSTR lpszText) {
CClientDC dc(this);
CFont* pOldFont = dc.SelectObject(GetFont()); // 使用列表框當前字型
CSize sz = dc.GetTextExtent(lpszText);
dc.SelectObject(pOldFont);
// 加上邊界間距 (左右各 3-4 像素)
int nExtent = sz.cx + 8;
if (nExtent > m_nMaxExtent) {
m_nMaxExtent = nExtent;
SetHorizontalExtent(m_nMaxExtent); // 觸發水平捲軸顯示/調整
}
}
void CDJListBox::RecalcHorizontalExtent() {
m_nMaxExtent = 0;
CClientDC dc(this);
CFont* pOldFont = dc.SelectObject(GetFont());
for (int i = 0; i < GetCount(); ++i) {
CString str; GetText(i, str);
CSize sz = dc.GetTextExtent(str);
m_nMaxExtent = max(m_nMaxExtent, sz.cx + 8);
}
dc.SelectObject(pOldFont);
SetHorizontalExtent(m_nMaxExtent);
}
WM_SETFONT)
void CDJListBox::OnSetFont(CFont* pFont, BOOL bRedraw) {
CListBox::OnSetFont(pFont, bRedraw);
m_pFont = pFont;
if (bRedraw) RecalcHorizontalExtent(); // 字型變更需重新計算所有項目寬度
}
OnSize)
void CDJListBox::OnSize(UINT nType, int cx, int cy) {
CListBox::OnSize(nType, cx, cy);
// 垂直捲軸出現會減少客戶區寬度,可能需要水平捲軸
// 這裡可選擇強制重新計算或依賴 SetHorizontalExtent 自動處理
// 若發現內容被截斷,可呼叫 RecalcHorizontalExtent()
}
DJListBox.h/.cpp。IDC_LIST。CDJListBox (而非 CListBox),變數名 m_list。m_list.AddString(...),水平捲軸將自動管理。AddString 計算 GetTextExtent 可能較慢。可延遲計算 (標記 dirty flag,OnPaint 或定時器批次更新)。GetTextExtent 正確處理。\t): GetTextExtent 視為單一字元寬度,若需對齊需自行展開或使用 DrawText DT_EXPANDTABS 計算。LBS_OWNERDRAWVARIABLE: 需在 MeasureItem 中同步更新項目寬度邏輯。