6

So, my end game here is to have a way to list items (like a TListView in vsReport) with the add/remove buttons inside the client area.

Ex:

|----------------|
|Old Item 1    X |
|Old Item 2    X |
|Add new item... |
|                |
|----------------|

If you know of a component that does this without all this extra work, please let me know!

So I picked out an red close "X" and am using a TJvTransparentButton (Jedi Components - JVCL) to display it. It handles the press/not pressed states and only shows the image. I original used a TButton but I didn't need all the fluff that goes around the glyph.

Now, I keep the image button in the record associated with each node.

Code is as follows:

procedure TfrmMain.AddNewAccount(const Username, Password: String);
var
  Data : PTreeData;
  XNode : PVirtualNode;
Begin
  XNode := vstAccounts.AddChild(nil);
  If vstAccounts.AbsoluteIndex(XNode) > -1 Then
    begin
    Data := vstAccounts.GetNodeData(Xnode);
    Data^.Column0 := Username;
    Data^.Column1 := '';
    Data^.DeleteButton := TJvTransparentButton.Create(nil);
    With Data^.DeleteButton Do
      begin
      Parent := vstAccounts;
      Left := 0;
      Top := 0;
      Width := 16;
      Height := 16;
      Anchors := [];
      AutoGray := False;
      BorderWidth := 0;
      FrameStyle := fsNone;
      Images.ActiveImage := iListView;
      Images.ActiveIndex := 0;
    end;
  end;
end;

In the OnAfterCellPaint event I manage the positioning of the image button like so:

procedure TfrmMain.vstAccountsAfterCellPaint(Sender: TBaseVirtualTree;
  TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  CellRect: TRect);
var
  Data : PTreeData;
begin
  If Column = 1 Then
    begin
    Data := vstAccounts.GetNodeData(Node);
    If Assigned(Data) Then
      begin
      With Data^.DeleteButton Do
        begin
        BoundsRect := CellRect;
      end;
    end;
  end;
end;

Now the problem is that this doesn't show the item at all. I know that the Image from the TImageList is fine because I can create the button at design time and it looks fine at runtime.

I also know that this code should work because if I make the TJvTransparentButton a regular TButton (without changing the code logic) it works just fine and shows up fine!

The only thing I can think of is that a TButton inherits from a TWinControl while the TJvTransparentButton inherits from a TControl.

Any ideas?

ThievingSix
  • 1,044
  • 1
  • 11
  • 23

2 Answers2

3

I assume the TJvTransparentButton is a TGraphicControl and as such is displayed as part of the Parent's background (that's why a Tlabel will always be behind a TEdit or TButton in the same Parent).
The TButton is a TWinControl and as such is painted on top of the Parent and above or below the other WinControls in the same Parent.

So, either, you paint yourself again the TJvTransparentButton after the regular drawing of the cell happened (updating BoundsRect is not enough) or you use a WinControl.
For instance, using a TPanel with the TJvTransparentButton in it should work.

Disclaimer: I'm not familiar with VirtualStringTree nor TJvTransparentButton ...

Francesca
  • 21,452
  • 4
  • 49
  • 90
  • You are correct, it is a TGraphicControl. I'm not sure how I would paint it again since I'm already doing logic in the OnAfterCellPaint. Your second solution is interesting though. – ThievingSix Dec 28 '11 at 00:25
  • So I changed it so that their is a TPanel as the parent, and that gets its Bounds changed. It works, but Transparency is a problem. If the Panels Transparent property is True, it flickers like mad. If it's false, it's background is black. I don't need it to be transparent, but my changes to the Color property aren't affecting it. Any ideas? – ThievingSix Dec 28 '11 at 00:50
  • 1
    play with the ParentBackground and DoubleBuffered. – Francesca Dec 28 '11 at 01:02
  • Ideally, you should create a descendent of TVirtualStringTree to add the button and override its painting. – Francesca Dec 28 '11 at 01:05
3

You're doing this in a wrong way. You must write your own editor for TVirtualStringTree which implements IVTEditLink interface. Then in OnCreateEditor event you need to create your editor:

procedure TForm1.VSTCreateEditor(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; out EditLink: IVTEditLink);
begin
  EditLink:=TStringEditLink.Create;
end;

You can get more info here.

Linas
  • 5,485
  • 1
  • 25
  • 35
  • Yes, I found that site through this link (http://stackoverflow.com/questions/2675094/delphi-listview-or-similar-with-owner-draw-button) which explains the same thing. But the last item of text in that answer was: "did you want a button visible in a cell column all the time? Could simulate the button with an image... like a dropdown mark on one side of the cell" So it is my understanding that the Editor only shows when you are editing. – ThievingSix Dec 28 '11 at 19:48