2013-07-05 78 views
7

我在Delphi中有一个TTreeView,节点在三个级别。在treeview节点中显示额外的文本,而不仅仅是node.text

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

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

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

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

enter image description here

我走到这一步,是这样的:

enter image description here

问题:

  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; 
+2

你的2号可能是与事实做到这一点的树措施的节点文本的宽度来确定焦点矩形,并不会采取你的额外文本我nto帐户。要解决这个问题,您必须将文本添加到节点的文本中,或者创建您自己的TTreeview后代,并找到一种方法来覆盖/钩入焦点矩形的宽度度量(快速阅读[documentation](http: /docwiki.embarcadero.com/Libraries/XE4/en/Vcl.ComCtrls.TTreeView)不会引发任何明显的事件)。 –

+1

正如@Marjan所说。没有什么比如'TVM_SETITEMRECT'和'TVM_SETITEMHEIGHT',通知消息或者用于设置节点宽度的宏。我会说,你将需要设置TTreeNode.Text属性值来适当扩展节点宽度。 – TLama

+0

不幸的是我不能设置TTreeNode.Text属性,因为这个值不应该与节点文本一起保存。 – beerwin

回答

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)); 
相关问题