Link to home
Start Free TrialLog in
Avatar of hakanfa
hakanfaFlag for Finland

asked on

TTreeView and different fonts within one node

Hello!
I'm using the TTreeView to mimic  the "folder tree" in MS Outlook. Is it possible to set different font colors within one node,
like when You have ex. e few underad mails in one folder the amount is displayed in blue, the other text is bolded black.

I suppose it can be done with OnCustomDrawItem, but cannot figure out how...

Ex. We have three nodes in a TreeView: "Drafts", "Inbox", "Sent Items". I would like the "Inbox" to be drawn as "Inbox" in Bold black and  after that "(12)" with
normal font in blue.


Any suggestions?


Hokki
Avatar of sas13
sas13
Flag of Russian Federation image

procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
var
  _bmp: TBitmap;
  _off: integer;
  _rect: TRect;
begin
 if Node.AbsoluteIndex = 0 then begin
  DefaultDraw := false;
  Sender.Canvas.Brush.Style := bsSolid;
  Sender.Canvas.Brush.Color := TTreeView(Sender).Color;
  Sender.Canvas.FillRect(Node.DisplayRect(false));
  _bmp := TBitmap.Create;
  if Assigned(TTreeView(Sender).Images) and TTreeView(Sender).Images.GetBitmap(Node.ImageIndex, _bmp) then
   Sender.Canvas.Draw(0, 1, _bmp);
  _bmp.Free;
  if cdsSelected in State then
   Sender.Canvas.Brush.Color := clHighlight;
  _rect := Node.DisplayRect(true);
  _rect.Right := Node.DisplayRect(false).Right;
  Sender.Canvas.TextRect(_rect, _rect.Left+2, 1, 'Inbox');
  Inc(_rect.Left, Sender.Canvas.TextWidth('Inbox '));
  Sender.Canvas.Font.Style := [fsBold];
  Sender.Canvas.TextRect(_rect, _rect.Left+2, 1, '(12)');
  Inc(_rect.Left, Sender.Canvas.TextWidth('(12) '));
  Sender.Canvas.Brush.Color := clBlue;
  Sender.Canvas.Font.Style := [];
  Sender.Canvas.TextRect(_rect, _rect.Left+2, 1, 'other textg');
  Inc(_rect.Left, Sender.Canvas.TextWidth('other textg')+4);
  _off := _rect.Left;
  _rect := Node.DisplayRect(true);
  _rect.Right := _off;
  if cdsFocused in State then
   Sender.Canvas.DrawFocusRect(_rect)
 end
end;
You might also find this functionality within the highly recommended VirtualTreeView from SoftGems

Take a look at
http://www.delphi-gems.com/VirtualTreeview/
Avatar of hakanfa

ASKER

Semen,
I'm sorry to say but I couldn't get Your code working as expected.. A few comments though, the "Inbox" is not always the first node (a small thing but..), Is it necessary to turn "DefaultDraw" off for modifying a portion of text? Can You help me a little more?


Mike,
I checked the VirtualTreeView (the demos) but couldn't find a suitable demo that shows these features.. You don't happen to have a demo using this component showing these features that I mentioned in my first message?

brdgs,
-hokki
VirtualTreeView requires some learning to do before you can use it effectively, but after you learn how to use it, it's defenitively a great tool.

Example of using VirtualTreeView and OnPanitText event

//** Node data
type
  PNodeData = ^TNodeData;
  TNodeData = record
    Text: string;
    ItemType: integer;
    Status: integer;
    AnObject: TSomeObject;
  end;

procedure TForm1.VirtualStringTree1PaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);
var
  data: PNodeData;
begin
  data := VirtualStringTree1.GetNodeData(Node);
  if data = nil then
    Exit;
  TargetCanvas.Font.Style := [];
  if data^.Status = 1 then
    TargetCanvas.Font.Style := [fsBold]
  if data^.ItemType = 1 then
    TargetCanvas.Font.Style := TargetCanvas.Font.Style  + [fsItalic];  
  if data^.AnObject.SomeFunction then
    TargetCanvas.Font.Color := clBlue;
end;

If you use instead TreeView, then you can do all in OnCustomDrawItem event.

Just keep DefaultDraw true and set needed font properties for canvas.

procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  DefaultDraw := true;
  if Node.Text = 'Some text' then
    Sender.Canvas.Font.Style := [fsBold];
  if Node.Data = @SomeVar then
    Sender.Canvas.Font.Color := clBlue;
end;
Avatar of hakanfa

ASKER

A comment..

I've tried to do it the simple way..
procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
var
 r:TRect;
begin
 if Node.Text = 'Inbox' then
 begin
  r:=Node.DisplayRect(True);
  Statusbar1.SimpleText:='Left:'+ IntToStr(r.Left)+','+ 'Right:'+ IntToStr(r.Right)+','+'Top:'+ IntToStr(r.Top)+','+'Bottom:'+ IntToStr(r.Bottom);
  Sender.Canvas.Font.Style := [];
  Sender.Canvas.Font.Name:='Tahoma';
  Sender.Canvas.Font.Size:=8;
  Sender.Canvas.TextOut(r.Right,r.Top,'(12)');
 end;
end;

This goes well almost..
1. The "Inbox" text is a a different font..? Why?
2. How do i gewt the text for "(12)" painted blue?
3. When I selected the node, the "(12)" text is also selected, I would like to avoid this (should be static)


Any Ideas?

-hokki
Avatar of hakanfa

ASKER

jpedef,

Thank You for showing the VirtualTreeView, but.. the change is so remarkable compared to an ordinary TreeView, that I would have to re-work the whole project.. what a shame. Anyhow, the other code (ordinary treeview) Do You think that You can support me with a little more detailed code? Like how to handle the Node.Data and as i mentioned before paint som "static" text in a different color?

brdgs,
Hokki
Avatar of hakanfa

ASKER

Hmm. doing some progress here..

I now get it painted "static" as I want, but still some problems.
1. how to handle the strange font for the other text
2. when you select the node, it paint a "shadow" of the text amended "(12)".

Code as follows: (what am I doing wrong??)

procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
var
 bmp:TBitMap;
 s:string;
 pt:TPoint;
 r:TRect;
begin
if Node.Text = 'Inbox' then
begin
 DefaultDraw:=True;
  s:='(12)' ;
  r:=Node.DisplayRect(false);
  BMP:=TBitmap.Create;
  BMP.Width:=Canvas.TextWidth(s);
  BMP.Height:=Canvas.TextHeight(S) ;
  bmp.Canvas.Font.Color:=clBlue;
  bmp.Canvas.Brush.Style:=bsClear;
  bmp.Canvas.TextOut(0,0,s);

  Pt.x:=r.Right+10;
  Pt.y:=r.Top;

  if INteger(BitBlt(sender.Canvas.Handle,Pt.x,Pt.y,BMP.Width,BMP.Height,BMP.Canvas.Handle,0,0,SRCCOPY)) = 0 then
   Statusbar1.SimpleText:='Error painting Node...';

  bmp.Free;

end;
end;
Avatar of hakanfa

ASKER

Hrmm..increasing to 500....
Avatar of hakanfa

ASKER

OK.. got it working. Little tricky with the handle.
Here's the code if someone needs it..

procedure TForm1.TreeView1CustomDrawItem(Sender: TCustomTreeView;
  Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean);
var
  bmp: TBitMap;
  s: string;
  pt: TPoint;
  r: TRect;
  DC: HWND;
begin
  if Node.Text = 'Inbox' then
  begin
    s := '(12)';
    Sender.Canvas.Font.Style := [fsBold];
    r := Node.DisplayRect(true);
    bmp := TBitmap.Create;
    bmp.Width := Canvas.TextWidth(s);
    bmp.Height := Canvas.TextHeight(S);
    bmp.Canvas.Font.Color := clBlue;
    bmp.Canvas.Brush.Style := bsClear;
    bmp.Canvas.TextOut(0, 0, s);
    Pt.x := r.Left + sender.Canvas.TextWidth(Node.Text)+6;
    Pt.y := r.Top + 2;
    DC := GetDC(sender.Handle);
    BitBlt(DC, pt.x, pt.y, BMP.Width, BMP.Height, BMP.Canvas.Handle, 0, 0, SRCCOPY);
    bmp.Free;
    ReleaseDC(sender.Handle, DC);
    DefaultDraw := True;
  end;
end;


-hokki
Avatar of aikimark
Having read this thread from an outsider's perspective, I think the question has been answered and points should be awarded to sas13 and jpedef.
Avatar of hakanfa

ASKER

Aikimark,
Would You please try the sas13 solution.! It doesent work (I did not get it workin anyway), how can I accept such an answer..??

-hokki
hokki,

I wrote my comments based on the information you told us "OK.. got it working".

<<Would You please try the sas13 solution>>
It wouldn't do any good, since I don't have the rest of your application and can't evaluate what you need for your user interface.

<<how can I accept such an answer?>>
1. keep working on the solution and ask questions.  This question is only 6 days old.
2. if the question rolls off the first page and it is urgent, you can post a 20 point question with a link to this one.
3. if you are close but have other questions, then close this one and open another question.
Avatar of hakanfa

ASKER

Aahh, now i understand. With "OK..got it working" I ment I figured out by my self..
As You can see from "my solution" there is nothing in common with the sas12 proposal.. You see?

-hokki
ASKER CERTIFIED SOLUTION
Avatar of modulo
modulo

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial