2013-07-05 50 views
7

Tôi có một TTreeView ở Delphi, với các nút ở ba cấp độ.Hiển thị văn bản bổ sung trong các nút treeview, không chỉ nút .tiếp theo

Tôi sử dụng dữ liệu nút để lưu trữ nhãn khác ngoài văn bản nút.

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

Tôi có sự kiện OnAdvancedCustomDrawItem, nơi tôi muốn hiển thị ExtraNodeLabel này trước văn bản nút. tôi muốn đạt được điều này:

  • Các văn bản màu xanh sẽ là nhãn phụ.
  • mục được tô sáng: hai từ đầu tiên cũng là một nhãn phụ

enter image description here

gì tôi đã nhận cho đến nay, là thế này:

enter image description here

vấn đề:

  1. Đối với một số lý do tôi không thể rút ra văn bản với phong cách khác nhau nếu tôi sử dụng DrawText/drawTextW (Tôi cần drawtextW vì dữ liệu unicode)
  2. Vấn đề khác là, rằng bất cứ điều gì ngoài hình chữ nhật tập trung rải rác là không thể nhấp vào

Những gì cần phải được giải quyết:

  1. Làm thế nào tôi có thể rút ra văn bản với phong cách khác nhau sử dụng DrawText/DrawtextW
  2. Làm thế nào có thể im ake toàn bộ văn bản có thể nhấp?

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

Số 2 của bạn có thể phải thực hiện với việc đo chiều rộng của văn bản nút để xác định hình chữ nhật tiêu điểm và không mất văn bản bổ sung của bạn vào tài khoản. Để giải quyết điều đó, bạn sẽ phải thêm văn bản vào văn bản của nút hoặc tạo dòng dõi TTreeview của riêng bạn và tìm cách ghi đè/móc vào đo chiều rộng cho hình chữ nhật tiêu điểm (đọc nhanh [tài liệu] (http://docwiki.embarcadero.com/Libraries/XE4/en/Vcl.ComCtrls.TTreeView) không hiển thị bất kỳ sự kiện hiển nhiên nào). –

+1

Giống như @Marjan nói. Không có gì giống như 'TVM_SETITEMRECT' cũng như' TVM_SETITEMHEIGHT', thông báo thông báo cũng như macro để đặt chiều rộng nút. Tôi muốn nói, bạn sẽ cần đặt giá trị thuộc tính 'TTreeNode.Text' để mở rộng thích hợp chiều rộng nút. – TLama

+0

Rất tiếc, tôi không thể đặt thuộc tính TTreeNode.Text, vì giá trị này không được lưu cùng với văn bản nút. – beerwin

Trả lời

2

Giải pháp của OP

tôi quản lý để giải quyết một phần bản vẽ tùy chỉnh, bằng cách định nghĩa một biến TFont, và sử dụng SelectObjectsetTextColor. Đặt màu phông chữ và kiểu hoạt động, nhưng đặt kích thước phông chữ thì không.

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; 

Nguồn: I used the idea from here


Cập nhật 2

tôi giải quyết vấn đề thứ hai bằng cách thiết lập tài sản RowSelect của treeview là true. Để làm việc này, tôi phải đặt thuộc tính ShowLines thành sai và vẽ tùy chỉnh các đường và các nút. Nó hoạt dộng bây giờ.


Cập nhật 3

tôi cải thiện các giải pháp cho vấn đề đầu tiên, bằng cách không tạo ra một phông chữ mới, nhưng việc lựa chọn font vải để hiển thị văn bản, và cách này tôi đã có thể thay đổi bất kỳ khía cạnh của phông chữ và cài đặt loại bỏ hệ thống cũng được áp dụng:

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