2005. április 4., hétfő

Create a TTreeView with checkboxes


Problem/Question/Abstract:

I need a TTreeView with a checkbox next to each item, much like the way most backup programs allow you to select files for backup (only I am not selecting files).

Answer:

Solve 1:

Checkboxes on TTreeView nodes. Use state images (2 and 3 for unchecked and checked box in example below)

procedure TForm1.FormCreate(Sender: TObject);
var
  bmp, temp: TBitmap;
  i: Integer;
begin
  bmp := TBitmap.create;
  try
    bmp.handle := LoadBitmap(0, PChar(OBM_CHECKBOXES));
    {bmp now has a 4x3 bitmap of divers state images used by checkboxes
                and radiobuttons}
    temp := TBitmap.Create;
    {image1.picture.bitmap := bmp;}
    try
      imagelist1.Width := bmp.width div 4;
      imagelist1.Height := bmp.Height div 3;
      with temp do
      begin
        width := bmp.width div 4;
        height := bmp.height div 3;
        for i := 0 to 3 do
        begin
          canvas.copyrect(canvas.cliprect, bmp.canvas, rect(i * width, 0, (i + 1) *
            width, height));
          imagelist1.AddMasked(temp, clSilver);
        end;
      end;
      label1.Caption := IntToStr(imagelist1.Count);
    finally
      temp.free;
    end;
  finally
    bmp.free
  end;
end;

procedure TForm1.TreeView1Click(Sender: TObject);
var
  pos: TPoint;
  node: TTreeNode;
begin
  pos := treeview1.screentoclient(mouse.CursorPos);
  node := treeview1.GetNodeAt(pos.x, pos.y);
  if assigned(node) then
    if htOnStateIcon in treeview1.GetHitTestInfoAt(pos.x, pos.y) then
      with node do
        case StateIndex of
          3: StateIndex := 2;
          2: StateIndex := 3;
        end;
end;


Solve 2:

Create an imagelist containing images of a checkbox checked and unchecked and put the following code into your program. Notice the special update procedure. You need to give an explicit update call since the treeview doesn't see you change the images.

procedure TForm1.TreeView1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  myNode: TTreeNode;
begin
  if htOnIcon in TreeView1.GetHitTestInfoAt(X, Y) then
  begin
    myNode := TreeView1.GetNodeAt(X, Y);
    if myNode.ImageIndex = 0 then
    begin
      myNode.ImageIndex := 1;
      myNode.StateIndex := 1;
      myNode.SelectedIndex := 1;
    end
    else
    begin
      myNode.ImageIndex := 0;
      myNode.StateIndex := 0;
      myNode.SelectedIndex := 0;
    end;
    RefreshNode(myNode);
  end;
end;

{Handles updating only a single node when a status image changes. This avoids
redrawing the entire tree, cutting down on flickering and speeding up the display.}

procedure TForm1.RefreshNode(Node: TTreeNode);
var
  R: TRect;
begin
  if Node <> nil then
  begin
    if not Node.IsVisible then
      Exit;
    R := Node.DisplayRect(False);
    InvalidateRect(TreeView1.Handle, @R, False);
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése