7

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

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

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

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

  • 蓝色文本将是额外的标签。
  • 突出显示的项目:前两个单词也是一个额外的标签

在此处输入图像描述

到目前为止,我得到的是:

在此处输入图像描述

问题:

  1. DrawText出于某种原因,如果我使用/ ,我将无法绘制具有不同样式的文本drawTextW(由于 unicode 数据,我需要 drawtextW)
  2. 另一个问题是,虚线焦点矩形之外的任何东西都是不可点击的

需要解决的问题:

  1. 如何使用DrawText/绘制具有不同样式的文本DrawtextW
  2. 如何使整个文本可点击?

代码:

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;
4

1 回答 1

2

OP的解决方案

SelectObject通过定义 TFont 变量并使用and ,我设法部分解决了自定义绘图setTextColor。设置字体颜色和样式有效,但设置字体大小无效。

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;

资料来源: 我从这里使用了这个想法


更新 2

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));
于 2014-05-15T09:56:17.370 回答