我在Tree1CustomDrawItem事件中写了如下代码
if cdsSelected in State then begin
    Tree1.Canvas.Brush.Color := clBlue;
    Tree1.Canvas.Font.Style := [fsBold];
    end
else
    begin
    tree1.Canvas.Font.Style := [];
end;
程序运行后,发现选中的节点也的的确确也能按我所想的那样着色
为蓝色,字体变为粗体,但点了另一个节点后,先前点的节点的字体及
着色也变回来了,只是在先前点的节点的后面仍有一点点未擦除的区域
,这是怎么回事?

解决方案 »

  1.   

    是用 Tree1.Refresh 吗?
    我用这个把程序给弄死了
      

  2.   

    请参考Delphi的Demos目录下的例子:
    unit CustomDrawTreeView;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ComCtrls, ExtDlgs, StdCtrls, ExtCtrls, ColorGrd, ImgList, Menus;type
      TCustomDrawForm = class(TForm)
        TV: TTreeView;
        ImageList: TImageList;
        MainMenu1: TMainMenu;
        Drawing1: TMenuItem;
        Font1: TMenuItem;
        Background1: TMenuItem;
        Color1: TMenuItem;
        Bitmap1: TMenuItem;
        DefaultDrawing1: TMenuItem;
        OnCustomDraw1: TMenuItem;
        OnCustomDrawItem1: TMenuItem;
        BrushStyle1: TMenuItem;
        Solid1: TMenuItem;
        Clear1: TMenuItem;
        Horizontal1: TMenuItem;
        Vertical1: TMenuItem;
        FDiagonal1: TMenuItem;
        BDiagonal1: TMenuItem;
        Cross1: TMenuItem;
        DiagCross1: TMenuItem;
        File1: TMenuItem;
        Exit1: TMenuItem;
        N2: TMenuItem;
        TVFontDialog: TFontDialog;
        Tile1: TMenuItem;
        Stretch1: TMenuItem;
        None1: TMenuItem;
        Selection1: TMenuItem;
        SelectedFontDialog: TFontDialog;
        BkgColorDialog: TColorDialog;
        SelBkgColorDialog: TColorDialog;
        SelectionBackground1: TMenuItem;
        ButtonColor1: TMenuItem;
        ButtonSize1: TMenuItem;
        ButtonColorDialog: TColorDialog;
        Image1: TImage;
        TreeView1: TMenuItem;
        Color2: TMenuItem;
        TVColorDialog: TColorDialog;
        CustomDraw1: TMenuItem;
        Font2: TMenuItem;
        procedure FormCreate(Sender: TObject);
        procedure TVCustomDraw(Sender: TCustomTreeView; const ARect: TRect;
          var DefaultDraw: Boolean);
        procedure TVCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
          State: TCustomDrawState; var DefaultDraw: Boolean);
        procedure TVGetImageIndex(Sender: TObject; Node: TTreeNode);
        procedure TVGetSelectedIndex(Sender: TObject; Node: TTreeNode);
        procedure Exit1Click(Sender: TObject);
        procedure Selection1Click(Sender: TObject);
        procedure Color1Click(Sender: TObject);
        procedure SelectionBackground1Click(Sender: TObject);
        procedure Solid1Click(Sender: TObject);
        procedure None1Click(Sender: TObject);
        procedure OnCustomDraw1Click(Sender: TObject);
        procedure OnCustomDrawItem1Click(Sender: TObject);
        procedure TVExpanded(Sender: TObject; Node: TTreeNode);
        procedure ButtonColor1Click(Sender: TObject);
        procedure ButtonSize1Click(Sender: TObject);
        procedure Drawing1Click(Sender: TObject);
        procedure Color2Click(Sender: TObject);
        procedure CustomDraw1Click(Sender: TObject);
        procedure Font2Click(Sender: TObject);
      private
        FButtonSize: Integer;
        FDefaultDraw,
        FDefaultDrawItem: Boolean;
        FBackgroundColor: TColor;
        FBrushStyle: TBrushStyle;
        procedure DrawButton(ARect: TRect; Node: TTreeNode);
        procedure DrawImage(NodeRect: TRect; ImageIndex: Integer);
        procedure SetCustomDraw(Value: Boolean);
        { Private declarations }
      public
        { Public declarations }
      end;var
      CustomDrawForm: TCustomDrawForm;implementation{$R *.dfm}procedure TCustomDrawForm.FormCreate(Sender: TObject);
    begin
      FBackgroundColor := clWindow;
      FDefaultDraw := True;
      FDefaultDrawItem := True;
      FBrushStyle := bsSolid;
      FButtonSize := 5;
      BkgColorDialog.Color := clWindow;
      SelBkgColorDialog.Color := clHighlight;
      TVFontDialog.Font.Assign(TV.Font);
      SelectedFontDialog.Font.Assign(TV.Font);
      SelectedFontDialog.Font.Color := clHighlightText;
      SelBkgColorDialog.Color := clHighlight;
      TVColorDialog.Color := TV.Color;
    end;procedure TCustomDrawForm.TVCustomDraw(Sender: TCustomTreeView; const ARect: TRect;
      var DefaultDraw: Boolean);
    begin
    //This event should be used to draw any background colors or images.
    //ARect represents the entire client area of the TreeView.
    //Use the TreeView's canvas to do the drawing.
    //Note that drawing a background bitmap is not really supported by CustomDraw,
    //so scrolling can get messy. Best to subclass the TreeView and handle scrolling
    //messages.
      with TV.Canvas do
      begin
        if None1.Checked then //no picture
        begin
          Brush.Color := BkgColorDialog.Color;
          Brush.Style := FBrushStyle;
          FillRect(ARect);
        end else
          if Tile1.Checked then //tile bitmap
          begin
            Brush.Bitmap := Image1.Picture.Bitmap;
              FillRect(ARect);
            end else //Stretch across the canvas.
                StretchDraw(ARect, Image1.Picture.Bitmap);
      end;
      DefaultDraw := FDefaultDraw;
      //setting DefaultDraw to false here prevents all calls to OnCustomDrawItem.
    end;procedure TCustomDrawForm.DrawButton(ARect: TRect; Node: TTreeNode);
    var
      cx, cy: Integer;
    begin
      cx := ARect.Left + TV.Indent div 2;
      cy := ARect.Top + (ARect.Bottom - ARect.Top) div 2;
      with TV.Canvas do
      begin
        Pen.Color := ButtonColorDialog.Color;
        //draw horizontal line.
        if Node.HasChildren then
        begin
          PenPos := Point(cx+FButtonSize, cy);
          LineTo(ARect.Left + TV.Indent + FButtonSize, cy);
        end else
        begin
          PenPos := Point(cx, cy);
          LineTo(ARect.Left + TV.Indent + FButtonSize, cy);
        end;    //draw half vertical line, top portion.
        PenPos := Point(cx, cy);
        LineTo(cx, ARect.Top-1);    if ((Node.GetNextVisible <> nil) and (Node.GetNextVisible.Level = Node.Level))
        or (Node.GetNextSibling <> nil) then
        //draw bottom portion of half vertical line.
        begin
          PenPos := Point(cx, cy);
          LineTo(cx, ARect.Bottom+1);
        end;      if Node.HasChildren then
        begin
          //Let's try a circular button instead
          Ellipse(cx-FButtonSize, cy-FButtonSize, cx+FButtonSize, cy+FButtonSize);      //draw the horizontal indicator.
          PenPos := Point(cx-FButtonSize+2, cy);
          LineTo(cx+FButtonSize-2, cy);
          //draw the vertical indicator if the node is collapsed
          if not Node.Expanded then
          begin
            PenPos := Point(cx, cy-FButtonSize+2);
            LineTo(cx, cy+FButtonSize-2);
          end;
        end;
            //now connect vertical lines of higher level nodes.
        Node := Node.Parent;
        while Node <> nil do
        begin
          cx := cx - TV.Indent;
          if Node.GetNextSibling <> nil then
          begin
            PenPos := Point(cx, ARect.Top);
            LineTo(cx, ARect.Bottom);
          end;
          Node := Node.Parent;
        end;
      end;
    end;procedure TCustomDrawForm.DrawImage(NodeRect: TRect; ImageIndex: Integer);
    var
      cy: Integer;
    begin
      cy := NodeRect.Top + (NodeRect.Bottom - NodeRect.Top) div 2;
      //center image in NodeRect.
      ImageList.Draw(TV.Canvas, NodeRect.Left, cy - TV.Images.Height div 2,
                     ImageIndex, True);
    end;
      

  3.   

    接着上面:
    procedure TCustomDrawForm.TVCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
      State: TCustomDrawState; var DefaultDraw: Boolean);
    var
      NodeRect: TRect;
    begin
      with TV.Canvas do
      begin
        //If DefaultDraw it is true, any of the node's font properties can be
        //changed. Note also that when DefaultDraw = True, Windows draws the
        //buttons and ignores our font background colors, using instead the
        //TreeView's Color property.
        if cdsSelected in State then
        begin
          Font.Assign(SelectedFontDialog.Font);
          Brush.Color := SelBkgColorDialog.Color;
        end;    DefaultDraw := FDefaultDrawItem;
        //DefaultDraw = False means you have to handle all the item drawing yourself,
        //including the buttons, lines, images, and text.
        if not DefaultDraw then
        begin
          //draw the selection rect.
          if cdsSelected in State then
          begin
            NodeRect := Node.DisplayRect(True);
            FillRect(NodeRect);
          end;
          NodeRect := Node.DisplayRect(False);      if None1.Checked then
          //no bitmap, so paint in the background color.
          begin
            Brush.Color := BkgColorDialog.Color;
            Brush.Style := FBrushStyle;
            FillRect(NodeRect)
          end
          else
            //don't paint over the background bitmap.
            Brush.Style := bsClear;      NodeRect.Left := NodeRect.Left + (Node.Level * TV.Indent);
          //NodeRect.Left now represents the left-most portion of the expand button
          DrawButton(NodeRect, Node);      NodeRect.Left := NodeRect.Left + TV.Indent + FButtonSize;
          //NodeRect.Left is now the leftmost portion of the image.
          DrawImage(NodeRect, Node.ImageIndex);      NodeRect.Left := NodeRect.Left + ImageList.Width;
          //Now we are finally in a position to draw the text.      TextOut(NodeRect.Left, NodeRect.Top, Node.Text);
        end;
      end;
    end;procedure TCustomDrawForm.TVGetImageIndex(Sender: TObject; Node: TTreeNode);
    begin
      if Node.HasChildren then
        if Node.Expanded then
          Node.ImageIndex := 3
        else
          Node.ImageIndex := 0
      else
        Node.ImageIndex := 1;
    end;procedure TCustomDrawForm.TVGetSelectedIndex(Sender: TObject; Node: TTreeNode);
    begin
      Node.SelectedIndex := Node.ImageIndex;
    end;procedure TCustomDrawForm.Exit1Click(Sender: TObject);
    begin
      Close;
    end;procedure TCustomDrawForm.Selection1Click(Sender: TObject);
    begin
      if SelectedFontDialog.Execute then
        TV.Repaint;
    end;procedure TCustomDrawForm.Color1Click(Sender: TObject);
    begin
      if BkgColorDialog.Execute then
        TV.Repaint;
    end;procedure TCustomDrawForm.SelectionBackground1Click(Sender: TObject);
    begin
      if SelBkgColorDialog.Execute then
        TV.Repaint;
    end;procedure TCustomDrawForm.Solid1Click(Sender: TObject);
    begin
      with Sender as TMenuItem do
      begin
        FBrushStyle := TBrushStyle(Tag);
        Checked := True;
      end;
      TV.Repaint;
    end;procedure TCustomDrawForm.None1Click(Sender: TObject);
    begin
      (Sender as TMenuItem).Checked := True;
      TV.Repaint;
    end;procedure TCustomDrawForm.OnCustomDraw1Click(Sender: TObject);
    begin
      FDefaultDraw := not FDefaultDraw;
      OnCustomDraw1.Checked := FDefaultDraw;
      TV.Repaint;
    end;procedure TCustomDrawForm.OnCustomDrawItem1Click(Sender: TObject);
    begin
      FDefaultDrawItem := not FDefaultDrawItem;
      OnCustomDrawItem1.Checked := FDefaultDrawItem;
      TV.Repaint;
    end;procedure TCustomDrawForm.TVExpanded(Sender: TObject; Node: TTreeNode);
    begin
      TV.Repaint;
    end;procedure TCustomDrawForm.ButtonColor1Click(Sender: TObject);
    begin
      if ButtonColorDialog.Execute then TV.Repaint;
    end;procedure TCustomDrawForm.ButtonSize1Click(Sender: TObject);
    var
      S: string;
    begin
      S := IntToStr(FButtonSize);
      if InputQuery('Change button size', 'Enter new size', S) then
        FButtonSize := StrToInt(S);
      TV.Repaint;  
    end;procedure TCustomDrawForm.Drawing1Click(Sender: TObject);
    begin
      ButtonColor1.Enabled := not OnCustomDrawItem1.Checked;
      ButtonSize1.Enabled := ButtonColor1.Enabled;
    end;procedure TCustomDrawForm.Color2Click(Sender: TObject);
    begin
      if TVColorDialog.Execute then
      begin
        TV.Color := TVColorDialog.Color;
        TV.Repaint;
      end;
    end;procedure TCustomDrawForm.SetCustomDraw(Value: Boolean);
    begin
      if not Value then
      begin
        TV.OnCustomDraw := nil;
        TV.OnCustomDrawItem := nil;
      end else
      begin
        TV.OnCustomDraw := Self.TVCustomDraw;
        TV.OnCustomDrawItem := Self.TVCustomDrawItem;
      end;
      Drawing1.Enabled := Value;
      TV.Repaint;
    end;procedure TCustomDrawForm.CustomDraw1Click(Sender: TObject);
    begin
      CustomDraw1.Checked := not CustomDraw1.Checked;
      SetCustomDraw(CustomDraw1.Checked);
    end;procedure TCustomDrawForm.Font2Click(Sender: TObject);
    begin
      if TVFontDialog.Execute then
        TV.Font.Assign(TVFontDialog.Font);
    end;end.
      

  4.   

    还不如直接告诉路径了。
    procedure TCustomDrawForm.TVCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode;
      State: TCustomDrawState; var DefaultDraw: Boolean);
    var
      NodeRect: TRect;
    begin
      with TV.Canvas do
      begin
        //If DefaultDraw it is true, any of the node's font properties can be
        //changed. Note also that when DefaultDraw = True, Windows draws the
        //buttons and ignores our font background colors, using instead the
        //TreeView's Color property.
        if cdsSelected in State then
        begin
          Font.Assign(SelectedFontDialog.Font);
          Brush.Color := SelBkgColorDialog.Color;
        end;    DefaultDraw := FDefaultDrawItem;
        //DefaultDraw = False means you have to handle all the item drawing yourself,
        //including the buttons, lines, images, and text.
        if not DefaultDraw then
        begin
          //draw the selection rect.
          if cdsSelected in State then
          begin
            NodeRect := Node.DisplayRect(True);
            FillRect(NodeRect);
          end;
          NodeRect := Node.DisplayRect(False);      if None1.Checked then
          //no bitmap, so paint in the background color.
          begin
            Brush.Color := BkgColorDialog.Color;
            Brush.Style := FBrushStyle;
            FillRect(NodeRect)
          end
          else
            //don't paint over the background bitmap.
            Brush.Style := bsClear;
    这一段说的比较详细!
      

  5.   

    Tree1.Canvas.Font.Style := [fsUnderline];
    即可