Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Глюк с Align у панели [D6, Win2k, WinXP]


Страницы:   1 2

--= Eagle =-- ©   (2006-09-11 11:53:00) 

Вобщем, есть наследник от TPanel, на котором лежит сплиттер (не стандартный, но всё же...). Сплиттер постоянно имеет какой-то Align. И если сплиттер у меня alLeft, а я бросаю на компоненту какую-то другую компоненту и ставлю ей Align=alTop, то сплиттер... правильно, располагается ПОД компонентой, т.к. выравнивание сверху/снизу имеет более высокий приоритет, чем выравнивание слева/справа. Как эту радость обойти? Я пытался создать на панели ещё одну панельку, на которую собственно и будут кидаться все остальные компоненты в режиме конструктора (и создаваться в рантайме), но почему-то компоненты, которые я кидаю в дизайн-тайме, не записываются как находящиеся на этой панели и не отображаются (в DFM их НЕ видно как будто они НЕ находятся на форме; при чём если выйти из режима просмотра DFM то получим сообщение о том, что этой панельки типа вообще-то и нима, и не стоит ли её убрать).
Как повлиять на ситуацию? Нужно чтобы если я установил сплитер справа, то он и занимал ВСЮ правую часть панели, игнорируя то, что какие-то компоненты могут быть заалигнены alTop/alBottom?

Как создаю панельку? А вот так:
 FContainer := TPanel.Create(Self);
 FContainer.Parent := Self;
 FContainer.BevelInner:=bvNone;
 FContainer.BevelOuter:=bvNone;
 FContainer.Align := alClient;
 FContainer.Name := 'Container';
 FContainer.SetSubComponent(True);

Если сделать FContainer := TPanel.Create(AOwner);то оно тоже будет глючить, хотя компоненты будут регаться... Но зато Container будет зареган в классе формы, что далеко не есть хорошо... :(

в ControlStyle флаг csAcceptControls установлен (по умолчанию)

В нете нарыл кусок нерабочего под D6 кода:

unit RzPnlPnl;

interface

uses
 SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
 Forms, Dialogs, ExtCtrls;

type
 TSubPanel = class(TPanel)
 protected
   procedure ReadState(Reader: TReader); override;
 end;

 TPanelPanel = class(TPanel)
 private
   FSubPanel: TSubPanel;
 protected
   procedure WriteComponents(Writer: TWriter); override;
   procedure ReadState(Reader: TReader); override;
 public
   constructor Create(AOwner: TComponent); override;
 end;

procedure Register;

implementation

procedure TSubPanel.ReadState(Reader: TReader);
var
 OldOwner: TComponent;
begin
 OldOwner := Reader.Owner;
   { Сохраняем старого владельца, что необходимо для PanelPanel }
 Reader.Owner := Reader.Root; { Задаем в качестве владельца форму }
 try
   inherited ReadState(Reader);
 finally
   Reader.Owner := OldOwner;
 end;
end;

constructor TPanelPanel.Create(AOwner: TComponent);
const
 Registered: Boolean = False;
begin
 inherited Create(AOwner);

 FSubPanel := TSubPanel.Create(Self);
 FSubPanel.Parent := Self;
 FSubPanel.SetBounds(20, 20, 200, 100);
 FSubPanel.Name := 'SomeName';

 if not Registered then
 begin
   Classes.RegisterClasses([TSubPanel]);
     { так TSubPanel может храниться в файле формы }
   Registered := True;
 end;

end;

procedure TPanelPanel.ReadState(Reader: TReader);
var
 OldOwner: TComponent;
 I: Integer;
begin
 for I := 0 to ControlCount - 1 do
   Controls[0].Free;

 OldOwner := Reader.Owner;
 Reader.Owner := Self;
   {Для чтения субкомпонентов, установите данный экземпляр в качестве родителя}
 try
   inherited ReadState(Reader);
 finally
   Reader.Owner := OldOwner;
 end;
end;

procedure TPanelPanel.WriteComponents(Writer: TWriter);
var
 I: Integer;
begin
 for I := 0 to ControlCount - 1 do
   Writer.WriteComponent(Controls);
end;

procedure Register;
begin
 RegisterComponents('Samples', [TPanelPanel]);
end;

end.


Переименовал WriteComponents в WriteState, но это не привело ни к каким хорошим результатам... Оно просто начало компилиться... Вобщем, чего бы ему такого сделать хорошего, чтобы оно решилось работать?

З.Ы. Я понимаю, что компонента будет нормально работать, если в дизайн-тайме на неё кинуть панель или фрейм с alClient, но это мне, увы, не подходит...


--= Eagle =--   (2006-09-11 17:36:00) [21]

Кстати, заметил ещё одну вещь, это уже немного серьёзнее - бОльшая часть свойств теперь не видна в инспекторе объектов...


--= Eagle =--   (2006-09-11 16:33:00) [22]


> Забыл, единственное НО. Так как саму встроенную панель мы
> в ресурс не сохраняем, то всё что мы броаем на панель-родитель
> перенесётся на на встроенную.


Огромное спасибо! Это работает. Хотя, правда говоря, неудобно, что компоненты, которые я кидаю в дизайнтайме не отображаются как находящиеся на панели (т.е. в Object TreeView они располагаются не в ветке моей компоненты, а являются как бы её sibling-ами). Это можно полечить? :)


DimaBr   (2006-09-11 14:32:00) [23]

Забыл, единственное НО. Так как саму встроенную панель мы в ресурс не сохраняем, то всё что мы броаем на панель-родитель перенесётся на на встроенную.


DimaBr   (2006-09-11 14:29:00) [24]

unit Panels;

interface
uses Classes, ExtCtrls,Controls;

type
TMyPanel = class(TCustomPanel)
 private
   fPanel: TPanel;
 public
   constructor Create(AOwner: TComponent);override;
   destructor Destroy;override;
   procedure GetChildren(Proc: TGetChildProc; Root: TComponent);override;
   procedure Loaded;override;
   procedure SetParent(AParent: TWinControl);override;
end;

procedure Register;
implementation

procedure Register;
begin
 RegisterComponents('Standard',[TMyPanel]);
end;

constructor TMyPanel.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 fPanel := TPanel.Create(self);
 Width := 200;
 Height := 200;
end;

destructor TMyPanel.Destroy;
begin
 FreeAndNil(fPanel);
 inherited;
end;

procedure TMyPanel.GetChildren(Proc: TGetChildProc; Root: TComponent);
var i: integer;
begin
inherited GetChildren(Proc,Root);
for i := 0 to fPanel.ControlCount - 1 do begin
  Proc( fPanel.Controls[i] );
end;{for}
end;

procedure TMyPanel.Loaded;
var i: integer;
begin
 inherited Loaded;
 for i :=  ControlCount-1 downto 0 do begin
   if (Controls[i] <> fPanel) then Controls[i].Parent := fPanel;
 end;{for}
end;

procedure TMyPanel.SetParent(AParent: TWinControl);
begin
 inherited;
 if fPanel <> nil then fPanel.Parent := self;
end;

end.


--= Eagle =--   (2006-09-11 12:48:00) [25]


> Внимательно изучаем GetChildten, ваш код должен быть приблизительно
> таким

DimaBr, прошу прощения, но такая задача стоит предо мной впервые при написании компонентов... Я немного "поигрался" с этим кодом, но мне и его тоже не удалось заставить правильно работать...
Можно попросить минимально рабочий пример, плиз?


DimaBr   (2006-09-11 12:07:00) [26]

Внимательно изучаем GetChildten, ваш код должен быть приблизительно таким


TPanelPanel = class(TPanel)
private
  FSubPanel: TSubPanel;
protected
  procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  procedure Loaded;override;
  constructor Create(AOwner: TComponent); override;
end;

procedure TPanelPanel.GetChildren(Proc: TGetChildProc; Root: TComponent);
var i: integer;
   Control: TControl;
begin
 inherited GetChildren(Proc,Root);
 for i := 0 to ControlCount - 1 do begin
   if Controls[i].Owner = Owner then Proc( Controls[i] );
 end;{for}
end;

procedure TPanelPanel.Loaded;
var i: integer;
begin
 inherited Loaded;
 for i := 0 to ControlCount-1 do
   if (Controls[i] <> FSubPanel) then
    Controls[i].Parent := FSubPanel;
end;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо