效果預覽
核心技術點
Style = lbOwnerDrawFixed:啟用固定高度自繪模式
ItemHeight = 50:設定每項高度
- 於
OnDrawItem 事件中完全自訂繪製邏輯
- 使用
RoundRect 繪製圓角矩形實現卡片立體感
- 支援選中/焦點狀態視覺區分
- 結合
ImageList 顯示圖示
- 單項顯示三行文字(主標題、副標題、備註)
完整實作程式碼
// 建構式初始化
__fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner) {
lbxMain->Style = lbOwnerDrawFixed;
lbxMain->Ctl3D = false; // 移除 3D 邊框
lbxMain->ItemHeight = 50; // 固定項高
pStrList = new TStringList;
for (int i = 0; i < 10; ++i) {
lbxMain->Items->Add("ListBox Items of " + String(i));
// 使用 0x03 作為分隔符,儲存第二、三行文字
pStrList->Add("Second of " + String(i) + String((char)0x03) + "Third of " + String(i));
}
}
// 核心繪製邏輯
void __fastcall TMainForm::lbxMainDrawItem(TWinControl* Control, int Index,
TRect& Rect, TOwnerDrawState State) {
// 背景與文字預設色
lbxMain->Canvas->Brush->Color = clWhite;
lbxMain->Canvas->Font->Color = clBlack;
lbxMain->Canvas->FillRect(Rect);
// 卡片圓角背景
lbxMain->Canvas->Brush->Color = TColor(0x00FFF7F7); // 淺藍底
lbxMain->Canvas->Pen->Color = TColor(0x00131315); // 深灰邊框
lbxMain->Canvas->RoundRect(Rect.Left + 3, Rect.Top + 3,
Rect.Right - 2, Rect.Bottom - 2, 8, 8);
// 內層圓角產生立體感
lbxMain->Canvas->RoundRect(Rect.Left + 3, Rect.Top + 3,
Rect.Right - 3, Rect.Bottom - 3, 5, 5);
// 選中狀態覆蓋
if (State.Contains(odSelected)) {
lbxMain->Canvas->Brush->Color = TColor(0x00FFB2B5); // 粉紅選中色
lbxMain->Canvas->RoundRect(Rect.Left + 3, Rect.Top + 3,
Rect.Right - 3, Rect.Bottom - 3, 5, 5);
lbxMain->Canvas->Font->Color = clBlue;
// 焦點虛線框處理(實際上是清除預設虛線框)
if (State.Contains(odFocused))
::DrawFocusRect(lbxMain->Canvas->Handle, &Rect);
}
// 繪製圖示(垂直置中)
ImageList1->Draw(lbxMain->Canvas, Rect.Left + 7,
Rect.Top + (lbxMain->ItemHeight - ImageList1->Height) / 2,
Index, true);
// 第一行:主標題
lbxMain->Canvas->TextOutA(Rect.Left + 42, Rect.Top + 4,
lbxMain->Items->Strings[Index]);
// 解析第二、三行文字
String strTemp = pStrList->Strings[Index];
int pos = strTemp.Pos((char)0x03);
String second = strTemp.SubString(1, pos - 1);
String third = strTemp.SubString(pos + 1, strTemp.Length());
// 第二行
lbxMain->Canvas->TextOutA(Rect.Left + 42, Rect.Top + 18, second.c_str());
// 第三行
lbxMain->Canvas->TextOutA(Rect.Left + 42, Rect.Top + 32, third.c_str());
}
輔助功能
- 點擊顯示項目:
OnClick 更新狀態列
- 雙擊編輯:彈出模態對話框編輯三行文字,回寫至 ListBox 與 StringList
- 無標題欄視窗拖移:
WM_SYSCOMMAND + 0xF012 (SC_DRAGMOVE)
- 視窗摺疊/展開:切換高度與按鈕圖示
關鍵細節提醒
- 分隔符選擇:使用不可見字元
0x03 避免與使用者輸入衝突
- 座標計算:文字輸出位置需手動換行,
ItemHeight 需配合行數設定
- 焦點框處理:
DrawFocusRect 重複呼叫可切換顯示/隱藏,此處用於清除預設虛線框
- 資源釋放:
FormDestroy 中 delete pStrList 防止記憶體洩漏
擴充方向
- 改用
lbOwnerDrawVariable 支援可變項高
- 加入滑鼠懸停高亮、動畫過渡效果
- 支援 HTML/RTF 富文本渲染
- 虛擬模式處理大量資料