2011-12-06 15 views
6

¿Es posible usar el TTreeView estándar para cambiar el Expandir y contraer la imagen?TTreeView - ¿Cambiar Expandir y contraer imagen?

no me refiero a las imágenes de nodo, me refiero a las pequeñas flechas junto a los nodos que tienen los niños, así:

enter image description here

Tu lugar ideal para mostrar las flechas como símbolos + y -, al igual que la estructura de componentes Delphi árbol:

enter image description here

Si es posible cambiar esto, ¿cómo hago para hacerlo?

Demostración de Trabajo sobre la base de respuesta de David

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. 

El resultado:

enter image description here

Respuesta

9

vistas de árbol en post-Windows Vista tiene dos temas alternativos. El tema que desea evitar se conoce como el tema del explorador. Quieres usar el tema estándar. Un control tiene que participar para obtener el tema del explorador. Lo hace a través de la API SetWindowTheme. El control de vista de árbol de VCL lo llama para habilitarlo. Lo hace al final de su método CreateWnd.

puede volver al tema estándar por deshacer el cambio como éste:

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; 

Este código está escrito para XE2. Si tienes un Delphi anterior, entonces creo que lo quieres así:

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

muy bien informado :) Tendré que probar lo último de su solución publicada. –

+0

Puede llamar a la función desde el formulario OnCreate para probarla. El enfoque CreateWnd es lo que necesita para "hacerlo bien". –

+0

funciona de maravilla, voy a editar la publicación superior con la forma en que implementé su respuesta. –

3

Además de la respuesta de David. Pon el siguiente código en una unidad extra y agrégalo a los usos después de la unidad ComCtrls. De esta forma puede usar el TTreeView estándar y cambiar el tema cuando lo desee. O regístrelo en su propio paquete si lo desea.

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; 

En versiones nunca Delphi también se puede utilizar un ayudante de clase para evitar la herencia adicional.

+0

Es importante hacer esto en CreateWnd porque se puede volver a crear el identificador de ventana. –

+1

Esto no es un ayudante de clase. Los ayudantes de clase son construcciones de código específicas (tipo THelper = clase auxiliar para THelpedClass o algo así, no estoy seguro de la sintaxis exacta aquí, ya que no los uso mucho). Lo que estás haciendo en tu ejemplo se conoce generalmente como una "clase de interceptor". –

+0

@Marjan Correcto. Y lo que es más, si va a utilizar un interceptor, 'CreateWnd' está disponible para anularlo. –

Cuestiones relacionadas