【问题标题】:TTreeView - Change Expand and Collapse Image?TTreeView - 更改展开和折叠图像?
【发布时间】:2011-12-06 20:48:01
【问题描述】:

是否可以使用标准的 TTreeView 来更改展开和折叠图像?

我不是指节点图像,我指的是有子节点旁边的小箭头,如下所示:

理想情况下,我希望箭头显示为 + 和 - 符号,如 Delphi 组件结构树:

如果可以改变这一点,我将如何去做?

基于大卫回答的工作演示

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, Themes, uxTheme;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  TMyTreeView = class(TTreeView)
  protected
    procedure CreateWnd; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyTreeView }

procedure TMyTreeView.CreateWnd;
begin
  inherited;
  if ThemeServices.Enabled and CheckWin32Version(6, 0) then
    SetWindowTheme(Handle, nil, nil);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  MyTree: TMyTreeView;
  Node: TTreeNode;
begin
  MyTree := TMyTreeView.Create(nil);
  with MyTree do
  begin
    Parent  := Self;
    Height  := 100;
    Width   := 100;
    Left    := 30;
    Top     := 30;

    Node := Items.Add(nil, 'Item');
    Items.AddChild(Node, 'Item');
    Node := Items.AddChild(Node, 'Item');
    Items.AddChild(Node, 'Item');
  end;
end;

end.

结果:

【问题讨论】:

    标签: delphi treeview


    【解决方案1】:

    后 Vista Windows 中的树视图有两个替代主题。您要避免的主题称为资源管理器主题。您想使用标准主题。控件必须选择加入才能获得资源管理器主题。它通过SetWindowTheme API 实现。 VCL 树视图控件调用它来选择加入。它在其CreateWnd 方法的末尾执行此操作。

    您可以通过撤消更改来恢复到标准主题,如下所示:

    type
      TMyTreeView = class(TTreeView)
      protected
        procedure CreateWnd; override;
      end;
    
    procedure TMyTreeView.CreateWnd;
    begin
      inherited;
      if StyleServices.Enabled and TOSVersion.Check(6) and StyleServices.IsSystemStyle then
        SetWindowTheme(Handle, nil, nil);
    end;
    

    此代码是为 XE2 编写的。如果您有早期的 Delphi,那么我认为您想要这样:

      if ThemeServices.Enabled and CheckWin32Version(6, 0) then
        SetWindowTheme(Handle, nil, nil);
    

    【讨论】:

    • 您可以从表单 OnCreate 中调用该函数来测试它。 CreateWnd 方法是您“正确行事”所需要的。
    • 非常感谢,我将编辑顶部帖子,说明我是如何实现您的答案的。
    【解决方案2】:

    我除了戴维斯回答。将以下代码放在一些额外的单元中,并将其添加到 ComCtrls 单元之后的使用中。这样您就可以使用标准的 TTreeView 并随时更改主题。如果您愿意,也可以将其注册到您自己的包中。

    type
      TTreeView = class(ComCtrls.TTreeView)
      private
        procedure SetExplorerTheme(const Value: Boolean);
      public
        property ExplorerTheme: Boolean write SetExplorerTheme;
      end;
    
    procedure TTreeView.SetExplorerTheme(const Value: Boolean);
    begin
      if ThemeServices.ThemesEnabled and CheckWin32Version(6, 0) then
        if Value then
          SetWindowTheme(Handle, 'Explorer', nil)
        else
          SetWindowTheme(Handle, nil, nil);
    end;
    

    在从不使用 Delphi 的版本中,您还可以使用类助手来避免额外的继承。

    【讨论】:

    • 在 CreateWnd 中这样做很重要,因为可以重新创建窗口句柄。
    • 这不是类助手。类助手是特定的代码构造(类型 THelper = THelpedClass 的类助手或类似的,我不确定这里的确切语法,因为我不经常使用它们)。您在示例中所做的通常称为interceptor class
    • @Marjan 正确。更重要的是,如果你要使用拦截器,那么CreateWnd 很容易被覆盖。
    • 回想起来也许不是,但你把你的评论移到“避免混淆”这一事实说明了很多...... :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 2018-12-13
    相关资源
    最近更新 更多