【问题标题】:VirtualStringTree - Embedding Controls In Cells - Control Not ShowingVirtualStringTree - 在单元格中嵌入控件 - 控件不显示
【发布时间】:2012-01-28 20:17:26
【问题描述】:

所以,我的最终目标是使用客户区域内的添加/删除按钮列出项目(如 vsReport 中的 TListView)。

例如:

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

如果您知道有一个组件无需所有这些额外工作就可以做到这一点,请告诉我!

所以我选择了一个红色的关闭“X”并使用 TJvTransparentButton (Jedi Components - JVCL) 来显示它。它处理按下/未按下状态并且只显示图像。我最初使用的是 TButton,但我不需要字形周围的所有绒毛。

现在,我将图像按钮保存在与每个节点关联的记录中。

代码如下:

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;

在 OnAfterCellPaint 事件中,我管理图像按钮的定位,如下所示:

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;

现在的问题是这根本不显示该项目。我知道 TImageList 中的图像很好,因为我可以在设计时创建按钮,并且在运行时看起来很好。

我也知道此代码应该工作,因为如果我将 TJvTransparentButton 设为常规 TButton(不更改代码逻辑),它就可以正常工作并且显示正常!

我唯一能想到的是,TButton 继承自 TWinControl,而 TJvTransparentButton 继承自 TControl。

有什么想法吗?

【问题讨论】:

    标签: delphi virtualtreeview tvirtualstringtree


    【解决方案1】:

    我假设 TJvTransparentButton 是一个 TGraphicControl,因此显示为父级背景的一部分(这就是为什么 Tlabel 将始终位于同一父级中的 TEdit 或 TButton 后面的原因)。
    TButton 是一个 TWinControl,因此被绘制在父级的顶部和同一父级中其他 WinControl 的上方或下方。

    因此,您可以在单元格的常规绘制发生后再次绘制 TJvTransparentButton(更新 BoundsRect 还不够),或者使用 WinControl。
    例如,使用带有 TJvTransparentButton 的 TPanel 应该可以工作。

    免责声明:我不熟悉 VirtualStringTree 也不熟悉 TJvTransparentButton ...

    【讨论】:

    • 你是对的,它是一个 TGraphicControl。我不确定如何再次绘制它,因为我已经在 OnAfterCellPaint 中进行了逻辑处理。不过,您的第二个解决方案很有趣。
    • 所以我改变了它,以便它们是一个作为父级的 TPanel,并且它的 Bounds 改变了。它有效,但透明度是一个问题。如果 Panels Transparent 属性为 True,它会疯狂闪烁。如果它是假的,它的背景是黑色的。我不需要它是透明的,但我对 Color 属性的更改不会影响它。有什么想法吗?
    • 使用 ParentBackground 和 DoubleBuffered。
    • 理想情况下,您应该创建 TVirtualStringTree 的后代来添加按钮并覆盖其绘制。
    【解决方案2】:

    你这样做是错误的。您必须为实现IVTEditLink 接口的TVirtualStringTree 编写自己的编辑器。然后在OnCreateEditor 事件中你需要创建你的编辑器:

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

    您可以通过here获取更多信息。

    【讨论】:

    • 是的,我通过这个链接 (stackoverflow.com/questions/2675094/…) 找到了该网站,它解释了同样的事情。但是该答案中的最后一项文本是:“您是否希望始终在单元格列中显示一个按钮?可以用图像模拟按钮......就像单元格一侧的下拉标记一样”所以它是我的理解是编辑器仅在您编辑时显示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 2015-08-31
    • 1970-01-01
    • 2016-11-24
    • 2019-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多