2013-07-05 19 views
7

Mam TTreeView w Delphi, z węzłami na trzech poziomach.Wyświetl dodatkowy tekst w węzłach drzewa, a nie tylko w węźle.text

Używam danych węzła do przechowywania innej etykiety oprócz tekstu węzła.

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

Mam OnAdvancedCustomDrawItem wydarzenie, gdzie chcę, aby wyświetlić ten ExtraNodeLabel przed tekstem węzła. pragnę osiągnąć:

  • niebieski tekst będzie dodatkowa etykieta.
  • higlighted pozycja: pierwsze dwa słowa są również dodatkowa etykieta

enter image description here

co mam do tej pory, jest to:

enter image description here

Problemy:

  1. Z jakiegoś powodu nie mogę wyciągnąć tekst z innym stylu czy używam DrawText/drawTextW (bo muszę drawtextW danych Unicode)
  2. Innym problemem jest to, że nic poza przerywaną ostrości prostokąta jest unclickable

Co musi zostać rozwiązany:

  1. Jak mogę wyciągnąć tekst z innym stylu, przy użyciu DrawText/DrawtextW
  2. W jaki sposób można im Czy klikalny jest cały tekst?

Kod:

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

Twój numer 2 ma prawdopodobnie związek z faktem, że środki drzewo szerokości tekstu z nim węzła w celu określenia prostokąta ostrości i które nie biorą twój dodatkowy tekst i konto nto. Aby rozwiązać problem, musisz albo dodać tekst do tekstu węzła, albo utworzyć własnego potomka TTreeview i znaleźć sposób na przesłonięcie/podpięcie do pomiaru szerokości prostokąta skupienia (szybki odczyt [dokumentacji] (http: // /docwiki.embarcadero.com/Libraries/XE4/en/Vcl.ComCtrls.TTreeView) nie wywołuje żadnych oczywistych zdarzeń). –

+1

Jest tak, jak mówi @Marjan. Nie ma to jak 'TVM_SETITEMRECT' ani' TVM_SETITEMHEIGHT', wiadomość powiadomienia ani makro do ustawienia szerokości węzła. Powiedziałbym, że będziesz musiał ustawić wartość właściwości 'TTreeNode.Text' dla właściwego rozszerzenia szerokości węzła. – TLama

+0

Niestety nie mogę ustawić właściwości TTreeNode.Text, ponieważ tej wartości nie należy zapisywać razem z tekstem węzła. – beerwin

Odpowiedz

2

Rozwiązanie przez OP

udało mi się częściowo rozwiązać własny rysunek, definiując zmienną TFont i używając SelectObject i setTextColor. Ustawienie koloru i stylu czcionki działa, ale ustawienie rozmiaru czcionki nie działa.

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; 

Źródło: I used the idea from here


Aktualizacja 2

I rozwiązać drugi problem przez ustawienie TreeView za RowSelect właściwość true. Aby to zrobić, musiałem ustawić właściwość ShowLines na wartość false, a niestandardowe narysować linie i przyciski. Teraz działa.


Update 3

I poprawił rozwiązanie pierwszego problemu, by nie tworzyć nową czcionkę, ale wybierając czcionkę płótno do wyświetlania tekstu, iw ten sposób udało mi się zmienić dowolny aspekt czcionki, a ustawienia systemu ClearType stosowane są także:

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