在树视图节点中显示额外的文本,而不仅仅是node.text

时间:2013-07-05 12:14:49

标签: delphi treeview delphi-5 custom-draw

我在Delphi中有一个TTreeView,节点有三个级别。

我使用节点数据来存储除节点文本之外的另一个标签。

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

我有一个OnAdvancedCustomDrawItem事件,我希望在节点文本之前显示此ExtraNodeLabel我希望实现这一目标:

  • 蓝色文字将是额外的标签。
  • higlighted item:前两个单词也是一个额外的标签

enter image description here

到目前为止我得到的是:

enter image description here

问题:

  1. 由于某种原因,如果我使用DrawText / drawTextW(由于unicode数据我需要drawtextW),我无法绘制不同风格的文字。
  2. 另一个问题是,虚线焦点矩形之外的任何内容都是不可点击的
  3. 需要解决的问题:

    1. 如何使用DrawText / DrawtextW
    2. 绘制不同风格的文字
    3. 如何使整个文字可点击?
    4. 代码:

      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;
      

1 个答案:

答案 0 :(得分:2)

OP的解决方案

我设法通过定义TFont变量并使用SelectObjectsetTextColor来部分解决自定义绘图。设置字体颜色和样式有效,但设置字体大小不会。

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;

<强>来源: I used the idea from here


更新2

我通过将treeview的RowSelect属性设置为true来解决第二个问题。 为此,要工作,我必须将ShowLines属性设置为false,并自定义绘制线条和按钮。它现在有效。


更新3

我改进了第一个问题的解决方案,通过不创建新字体,但选择用于显示文本的画布字体,这样我就可以更改字体的任何方面,并且还应用了系统cleartype设置:

// 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));