TTreeView 的 TTreeNode 無內建 Enabled 屬性。本文實作完整的節點禁用機制:灰色字體顯示 + 禁止選取,透過 Data 屬性標記狀態、OnCustomDrawItem 自繪、OnChanging 攔截選取。
Node->Data(void*),NULL=啟用,(void*)0xFFFF=禁用OnCustomDrawItem 事件中依狀態設定 Canvas->Font->Color = clGrayOnChanging 事件中檢查目標節點狀態,設定 AllowChange
// 改變指定節點的啟用/禁用狀態
// bEnable: true=啟用, false=禁用
// pNode: 目標節點
void __fastcall CrnEnableTreeNode(bool bEnable, TTreeNode* pNode) {
// 規則:啟用時 Data=NULL,禁用時 Data=0xFFFF
pNode->Data = bEnable ? NULL : (void*)0xFFFF;
// 強制重繪 TreeView 更新視覺
pNode->TreeView->Invalidate();
}
void __fastcall TForm1::TreeView1CustomDrawItem(
TCustomTreeView* Sender, TTreeNode* Node,
TCustomDrawState State, bool& DefaultDraw) {
// 檢查節點是否被禁用
if ((int)Node->Data == 0xFFFF) {
// 禁用節點:灰色字體
Sender->Canvas->Font->Color = clGray;
}
// DefaultDraw=true 讓系統繼續預設繪製流程
}
void __fastcall TForm1::TreeView1Changing(
TObject* Sender, TTreeNode* Node, bool& AllowChange) {
// 即將選中 Node 時檢查狀態
AllowChange = ((int)Node->Data != 0xFFFF);
// 禁用節點 → AllowChange=false → 取消選取變更
}
void __fastcall TForm1::Button1Click(TObject* Sender) {
// 禁用目前選中的節點
if (TreeView1->Selected) {
CrnEnableTreeNode(false, TreeView1->Selected); // false = 禁用
}
}
void __fastcall TForm1::Button2Click(TObject* Sender) {
// 啟用第二個節點(索引 1)
CrnEnableTreeNode(true, TreeView1->Items->Item[1]); // true = 啟用
}

禁用節點呈現灰色字體,滑鼠點擊無法選中,鍵盤導航也會跳過。
改用其他標記方式:
TTreeNode 加入 bool Enabled 欄位TDictionary<TTreeNode*, bool> 外部映射Node->Index + Node->Level 組合鍵查找外部狀態表
void DisableSubTree(TTreeNode* root, bool disable) {
CrnEnableTreeNode(!disable, root);
for (int i = 0; i < root->Count; ++i) {
DisableSubTree(root->Item[i], disable);
}
}
if ((int)Node->Data == 0xFFFF) {
Sender->Canvas->Font->Color = clGray;
Sender->Canvas->Font->Style = TFontStyles() << fsItalic;
}
OnCustomDrawItem 需 TreeView->CustomDraw = true(設計時勾選)Invalidate() 觸發重繪,大量節點頻繁切換時可考慮 BeginUpdate/EndUpdateTreeView->Selected = disabledNode 會被 OnChanging 攔截)透過 Data 屬性標記、OnCustomDrawItem 視覺回饋、OnChanging 互動攔截三步驟,即可為 TTreeView 實作完整的節點啟用/禁用功能。此法無需繼承元件、相容性佳、擴充性強,適合企業級應用的樹狀介面權限控制需求。