標準 CListCtrl 難以實現「屬性名 + 值」的異構編輯體驗 (文字框、下拉框、複選框混合)。自研屬性列表控件 (CPropertyList) 內建編輯/下拉/自定義繪製,適合屬性視窗、設定面板、物件檢視器。
enum ITEM_TYPE { YJ_FOLDER, YJ_ITEM };
enum EDIT_TYPE { YJ_EDIT, YJ_LISTBOX, YJ_COMBO, YJ_CHECK };
struct YJPropertyItem {
int nLevel; // 巢狀層級 (0=根)
ITEM_TYPE nType; // 資料夾/項目
EDIT_TYPE nEditType; // 編輯樣式
CString strName; // 屬性名
CString strValue; // 當前值
CString strOptions; // 下拉選項,# 分隔 (如 "選項1#選項2")
BOOL bEnabled; // 是否可編輯
};
BEGIN_CREATE_NODE
BEGIN_YJITEM(0, YJ_FOLDER, YJ_EDIT, _T("檔案"), _T("檔案"))
BEGIN_YJITEM(1, YJ_ITEM, YJ_LISTBOX, _T("開啟"), _T("文檔#程式#文字"))
BEGIN_YJITEM(1, YJ_ITEM, YJ_EDIT, _T("另存新檔"), _T(""))
BEGIN_YJITEM(0, YJ_FOLDER, YJ_EDIT, _T("編輯"), _T(""))
BEGIN_YJITEM(1, YJ_ITEM, YJ_CHECK, _T("自動儲存"), _T(""))
END_CREATE_NODE
BEGIN_CREATE_NODE 宣告臨時陣列,BEGIN_YJITEM 填充 YJPropertyItem,END_CREATE_NODE 生成 std::vector<YJPropertyItem*> 並附加到控件。LVS_OWNERDATA,按需繪製,支援萬筆資料不卡頓。LVN_BEGINLABELEDIT 通知中,根據 nEditType 建立 CEdit/CComboBox/CButton,定位於 subitem 矩形區,LVN_ENDLABELEDIT 回寫資料。NM_CUSTOMDRAW 階段繪製層級縮進圖示、資料夾展開/摺疊箭頭、唯讀灰色、高亮選中列。VK_RETURN 進入編輯、VK_ESCAPE 取消、左右鍵 展開/摺疊資料夾。// 對話框初始化
CRATE_STRUCT(&m_propertyList); // 巨集展開並建構內部資料
m_propertyList.Invalidate(); // 觸發重繪
// 遍歷取值
for (int i = 0; i < m_propertyList.GetSize(); ++i) {
YJPropertyItem* pItem = m_propertyList.m_List[i];
TRACE(_T("%s = %s\n"), pItem->strName, pItem->strValue);
}
YJ_COLOR (顏色選擇器)、YJ_FONT (字型對話框)、YJ_FILE (檔案選擇) 編輯類型。SetValue/GetValue 以字串鍵值對操作,便於序列化 JSON/XML。