首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi TreeView 模擬複選框與單選鈕:以 StateImage 圖示切換實現勾選功能

     編輯:Delphi

Windows 檔案總管左側的樹狀結構是 TreeView 控制項的經典應用。Delphi 內建的 TTreeView 雖支援節點圖示,但無法直接內嵌 CheckBox 或 RadioButton。本文介紹一種「以圖示模擬」的輕量級方案:利用 StateImages 屬性 切換「勾選/未勾選」圖示,配合滑鼠鍵盤事件,實現直觀的節點選取功能。

檔案總管樹狀結構示意

核心思路:StateImage 圖示切換法

相比繼承重寫組件的高複雜度,利用 TreeView 內建的 StateImages 機制:

  • 準備兩組圖示:複選框(未勾選/勾選)與 單選鈕(未選中/選中)
  • 節點的 StateIndex 屬性指向 StateImages 中的圖示索引
  • 點擊節點狀態圖示區域時,切換 StateIndex 即可視覺呈現狀態變化

模擬複選框與單選鈕效果圖

實作步驟

1. 設計階段:設定 StateImages

  • 拖曳 ImageList 組件,加入 4 張 16x16 圖示(建議順序):
    0: 複選框未勾選、1: 複選框勾選、2: 單選鈕未選、3: 單選鈕選中
  • 將 TreeView 的 StateImages := ImageList1

2. 核心邏輯:統一的狀態切換程序

// 狀態索引常數(對應 ImageList 索引)
const
  cFlatUnCheck       = 0; // 複選框未勾選
  cFlatChecked       = 1; // 複選框勾選
  cFlatRadioUnCheck  = 2; // 單選鈕未選
  cFlatRadioChecked  = 3; // 單選鈕選中

procedure ToggleTreeViewCheckBoxes(Node: TTreeNode;
  cUnChecked, cChecked, cRadioUnchecked, cRadioChecked: Integer);
var
  tmp: TTreeNode;
begin
  if not Assigned(Node) then Exit;

  // 複選框模式:單純切換
  if Node.StateIndex = cUnChecked then
    Node.StateIndex := cChecked
  else if Node.StateIndex = cChecked then
    Node.StateIndex := cUnChecked
  // 單選鈕模式:同層級互斥
  else if Node.StateIndex = cRadioUnchecked then begin
    tmp := Node.Parent;
    if not Assigned(tmp) then
      tmp := TTreeView(Node.TreeView).Items.GetFirstNode
    else
      tmp := tmp.GetFirstChild;
    while Assigned(tmp) do begin
      if tmp.StateIndex in [cRadioUnchecked, cRadioChecked] then
        tmp.StateIndex := cRadioUnchecked;
      tmp := tmp.GetNextSibling;
    end;
    Node.StateIndex := cRadioChecked;
  end;
end;

3. 事件綁定:滑鼠點擊與鍵盤空白鍵

滑鼠點擊節點狀態圖示區域時:

procedure TForm1.TreeView1Click(Sender: TObject);
var
  P: TPoint;
begin
  GetCursorPos(P);
  P := TreeView1.ScreenToClient(P);
  // 判斷點擊位置是否在 StateIcon 區域
  if htOnStateIcon in TreeView1.GetHitTestInfoAt(P.X, P.Y) then
    ToggleTreeViewCheckBoxes(TreeView1.Selected,
      cFlatUnCheck, cFlatChecked, cFlatRadioUnCheck, cFlatRadioChecked);
end;

鍵盤空白鍵切換選中節點:

procedure TForm1.TreeView1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if (Key = VK_SPACE) and Assigned(TreeView1.Selected) then
    ToggleTreeViewCheckBoxes(TreeView1.Selected,
      cFlatUnCheck, cFlatChecked, cFlatRadioUnCheck, cFlatRadioChecked);
end;

4. 取得勾選結果範例

放置 Button 與 Memo,點擊按鈕顯示目前節點狀態:

procedure TForm1.Button1Click(Sender: TObject);
var
  BoolResult: Boolean;
  tn: TTreeNode;
begin
  if Assigned(TreeView1.Selected) then begin
    tn := TreeView1.Selected;
    BoolResult := tn.StateIndex in [cFlatChecked, cFlatRadioChecked];
    Memo1.Text := tn.Text + #13#10 + 'Selected: ' + BoolToStr(BoolResult, True);
  end;
end;

執行結果:Memo 顯示節點文字與勾選狀態

優缺點分析與擴充建議

優點缺點/限制
零組件繼承,幾行代碼即可完成非真實 CheckBox,無法直接綁定資料感知組件
效能極佳,無額外視窗控制代碼開銷需自行維護狀態邏輯(如父子節點聯動)
視覺風格完全可控(自訂圖示)無法響應螢幕閱讀器等無障礙 API

進階擴充方向:

  • 實作「父節點勾選 → 子節點全勾選」的遞迴邏輯
  • 結合 OnCustomDrawItem 繪製更豐富的節點樣式
  • 將狀態持久化至資料庫或 INI 檔

專業級擴充效果示意

這種「以圖示模擬互動控制項」的技巧,同樣適用於 ListView、ListBox 等支援 StateImages 的組件,是 Delphi 開發者實用的 UI 進階技法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved