delphitreeviewdelphi-5custom-draw

Display extra text in treeview nodes, not just node.text


I have a TTreeView in Delphi, with nodes at three levels.

I use node data to store another label besides the node text.

Type
  TNodeData = class
    ExtraNodeLabel: WideString;
    //... other members
  end;

I have an OnAdvancedCustomDrawItem event, where i want to display this ExtraNodeLabel before the node text. I wish to achieve this:

enter image description here

What i got so far, is this:

enter image description here

Problems:

  1. For some reason i can't draw text with different style if i use DrawText/drawTextW (I need drawtextW because of unicode data)
  2. The other problem is, that anything outside the dotted focus rectangle is unclickable

What needs to be solved:

  1. How can i draw text with different style using DrawText/DrawtextW
  2. How can i make the whole text clickable?

Code:

procedure TMainForm.TntTreeView1AdvancedCustomDrawItem(
  Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState;
  Stage: TCustomDrawStage; var PaintImages, DefaultDraw: Boolean);
var
  txtrect, fullrect : TRect;
  DC: HDC;
  fs: integer;
  fc: TColor;
  ExtralabelRect: TRect;
  nData: TNodeData;
begin
  nData := nil;

  if assigned(Node.Data) then begin
    nData := TNodeData(Node.Data);
  end;

  DC := TntTreeView1.canvas.Handle;
  txtRect := Node.DisplayRect(True);    
  fullrect := Node.DisplayRect(False);

  if stage = cdPostPaint then begin
    TntTreeView1.Canvas.FillRect(txtRect);
    if (cdsFocused In State) And (cdsSelected in State) then begin
      DrawFocusRect(DC,txtRect);
    end;

    txtRect.Left := txtRect.Left + 1;
    txtRect.Top := txtRect.Top + 1;
    txtRect.Right := txtRect.Right - 1;
    txtRect.Bottom := txtRect.Bottom - 1;

    ExtralabelRect := txtRect;

    fs := TntTreeView1.Canvas.Font.size;
    fc := TntTreeView1.Canvas.Font.Color;

    if (nData <> nil) And (nData.ExtraNodeLabel <> '') then begin
      TntTreeView1.Canvas.Font.Size := 7;
      TntTreeView1.Canvas.Font.color := clBlue;
      DrawTextW(
        DC,
        PWideChar(nData.ExtraNodeLabel),
        Length(nData.ExtraNodeLabel),
        ExtraLabelRect,
        DT_LEFT or DT_CALCRECT or DT_VCENTER
      );

      DrawTextW(
        DC,
        PWideChar(nData.ExtraNodeLabel),
        Length(nData.ExtraNodeLabel),
        ExtraLabelRect,
        DT_LEFT or DT_VCENTER
      );

      txtRect.right := txtRect.Right + ExtraLabelRect.Right + 5;
      txtRect.Left := ExtraLabelRect.Right + 5;
    end;

    TntTreeView1.Canvas.Font.Size := fs;
    TntTreeView1.Canvas.Font.color := fc;

    DrawTextW(
      DC,
      PWideChar((Node as TTntTreeNode).Text),
      -1,
      txtRect,
      DT_LEFT or DT_VCENTER
    );
  end;
end;

Solution

  • Solution by the OP

    I managed to partially solve custom drawing, by defining a TFont variable, and using SelectObject and setTextColor. Setting font color and style works, but setting the font size doesn't.

    var 
      nFont: TFont;
    begin
      DC := TntTreeView1.Canvas.Handle;
      NFont := TFont.Create;
    
      // rest of the code here ...
    
      // i tried to set nFont.Size, but it doesn't seem to work
      nFont.Size := 7;
      nFont.Color := colorToRGB(clBlue);
      nFont.Style := TntTreeview1.Font.Style + [fsBold];
    
      SelectObject(DC,NFont.Handle);
      SetTextColor(DC,colortoRGB(clBlue));
    
      DrawTextW(
        DC,
        PWideChar(nData.nodeLabel),
        Length(nData.nodeLabel),
        ExtraLabelRect,
        DT_LEFT or DT_VCENTER
      );
    
      // rest of the code here
    end;
    

    Source: I used the idea from here


    Update 2

    I solved the second problem by setting the treeview's RowSelect property to true. For this, to work, i had to set the ShowLines property to false, and custom draw the lines and the buttons. It works now.


    Update 3

    I improved the solution for the first problem, by not creating a new font, but selecting the canvas font for displaying text, and this way i was able to change any aspect of the font, and the system cleartype settings are also applied:

    // set font size for the canvas font (font style can be set the same time)
    TntTreeView1.Canvas.Font.Size := 7;
    
    // select canvas font for DC
    SelectObject(DC,TntTreeView1.Canvas.Font.Handle);
    
    // set font color
    SetTextColor(DC,colortoRGB(clBlue));