Высота элемента в древовидном представлении не изменяется, несмотря на отправку сообщения с помощью Perform - PullRequest
1 голос
/ 09 июля 2011

У меня есть вид дерева в качестве главного меню. После запуска программы я добавляю новые подпункты.

Тогда я делаю TreeView1.Perform(TVM_SETITEMHEIGHT, 28, 0);

Во время разработки я установил для свойства Положение формы значение poDesigned. Почему TreeView1.Perform не работает, если я выполняю Position := poScreenCenter; во время выполнения?

Пожалуйста, посмотрите видео этой проблемы: http://liga -installer.realservers.info / tv.mp4

Это мой код:

procedure TForm1.FormCreate(Sender: TObject);
begin
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu1');
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu2');
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu3');
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu4');
  TreeView1.Perform(TVM_SETITEMHEIGHT, 28, 0);
  Position:=poScreenCenter;
end;

Ответы [ 2 ]

7 голосов
/ 10 июля 2011

Ответ NGLN дает объяснение проблемы.

Если вам нужно только установить Position (или любое другое свойство формы, которое приведет к воссозданию окна (в техническом смысле)), в то же время вы устанавливаете высоту элементов древовидного представления Вы можете сделать

procedure TForm1.FormCreate(Sender: TObject);
begin
  Position := poDesigned;
  TreeView1.HandleNeeded;
  TreeView1.Perform(TVM_SETITEMHEIGHT, 28, 0);
end;
4 голосов
/ 10 июля 2011

Проблема заключается в том, что установка свойства Position формы приводит к вызову RecreateWnd. RecreateWnd означает уничтожение объекта экрана Windows и его создание с нуля. Похоже, что это необходимо (или самый простой способ), чтобы полностью реализовать все эффекты изменения этого свойства. Воссоздание оконных дескрипторов не редкость: например, изменение BorderStyle формы или даже элемента управления Edit приводит к вызову RecreateWnd.

RecreateWnd каскадно воссоздает все дочерние оконные элементы управления, в том числе и TreeView. Обычно компонент знает из своих внутренних компонентов (свойства, личные данные), как воссоздать себя. Например: TreeView сохраняет свои узлы во временном потоке памяти до уничтожения дескриптора и загружает его обратно после воссоздания дескриптора.

Итак, кто виноват: свойство Position формы, TreeView или ни то, ни другое? При отсутствии свойства ItemHeight для TreeView вы вынуждены вручную отправлять сообщение WinAPI. И это модификация элемента управления, который не зарегистрирован VCL. Пока объяснение, почему это происходит.

Лучшее решение - убедиться, что ваша настройка выполняется каждый раз, когда TreeView воссоздается. К сожалению, для этого нет событий. Вам нужно будет переопределить CreateWnd (см. Обновление ниже). Но если оставить свойства Ctl3D и BorderStyle без изменений, это также можно контролировать на уровне родителя. Я перешел к переопределению CM_ShowingChanged, потому что TreeView, к сожалению, еще не полностью перестроен после TForm1.CreateWnd:

TForm1 = class(TForm)
  TreeView1: TTreeView;
  ...
private
  procedure CMShowingChanged(var Message: TMessage);
    message CM_SHOWINGCHANGED;
end;

procedure TForm1.CMShowingChanged(var Message: TMessage);
begin
  inherited;
  TreeView1.Perform(TVM_SETITEMHEIGHT, 28, 0);
end;

Обновление:

Как указано в комментарии ниже, вот решение с переопределением TTreeView.CreateWnd:

unit Unit1;

interface

uses
  Windows, Classes, Controls, Forms, StdCtrls, ComCtrls, CommCtrl, XPMan;

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

  TForm1 = class(TForm)
    TreeView1: TTreeView;
    XPManifest1: TXPManifest;
    procedure FormCreate(Sender: TObject);
  end;

implementation

{$R *.dfm}

{ TTreeView }

procedure TTreeView.CreateWnd;
begin
  inherited CreateWnd;
  Perform(TVM_SETITEMHEIGHT, 38, 0);
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu1');
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu2');
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu3');
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu4');
  Position := poScreenCenter;
end;

end.

И если вам не нравится подкласс TTreeView, переопределите CreateWnd формы, но в этом случае вам нужно вызвать HandleNeeded, как ответил Andreas Rejbrand :

unit Unit1;

interface

uses
  Windows, Classes, Controls, Forms, StdCtrls, ComCtrls, CommCtrl, XPMan;

type
  TForm1 = class(TForm)
    TreeView1: TTreeView;
    XPManifest1: TXPManifest;
    procedure FormCreate(Sender: TObject);
  protected
    procedure CreateWnd; override;
  end;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu1');
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu2');
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu3');
  TreeView1.Items.AddChild(TreeView1.Items.Item[0],'Sub Menu4');
  Position := poScreenCenter;
end;

procedure TForm1.CreateWnd;
begin
  inherited CreateWnd;
  TreeView1.HandleNeeded;
  TreeView1.Perform(TVM_SETITEMHEIGHT, 38, 0);
end;

end.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...