Respect всем!
Классно придумано в этой проге — содержимое основной области имеет совершенно разный вид в зависимости от того, с чем работаем. Причем — не MDI. Ну, на MFC это ясно как делается — классический пример Document/View — а что Delphi?. Всяко приятнее (и продуктивнее) рисовать все в дизайне, чем писать всепую. Я знаю, в LMD Tools есть компонент TFormDisplay или как-то так — он позволяет отобразить форму так, как будто она TPanel. Красть неохота, а идея нравится. Есть какие-нибудь мысли? Мне только направление подскажите, я сам как-нибудь...
Здравствуйте, BaSergey, Вы писали:
BS>Respect всем! BS>Классно придумано в этой проге — содержимое основной области имеет совершенно разный вид в зависимости от того, с чем работаем. Причем — не MDI. Ну, на MFC это ясно как делается — классический пример Document/View — а что Delphi?. Всяко приятнее (и продуктивнее) рисовать все в дизайне, чем писать всепую. Я знаю, в LMD Tools есть компонент TFormDisplay или как-то так — он позволяет отобразить форму так, как будто она TPanel. Красть неохота, а идея нравится. Есть какие-нибудь мысли? Мне только направление подскажите, я сам как-нибудь...
Есть такая вещь, называется TFrame. Делаешь панель, а в нее вставляешь frame с align=alClient. Подменяешь инстансы фреймов на ходу.
... << RSDN@Home 1.0 beta 6 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, BaSergey, Вы писали:
BS>Respect всем! BS>Классно придумано в этой проге — содержимое основной области имеет совершенно разный вид в зависимости от того, с чем работаем. Причем — не MDI. Ну, на MFC это ясно как делается — классический пример Document/View — а что Delphi?. Всяко приятнее (и продуктивнее) рисовать все в дизайне, чем писать всепую. Я знаю, в LMD Tools есть компонент TFormDisplay или как-то так — он позволяет отобразить форму так, как будто она TPanel. Красть неохота, а идея нравится. Есть какие-нибудь мысли? Мне только направление подскажите, я сам как-нибудь...
При некотором желании содержание формы можно пропарсить и положить на TPanel (с сохранением значений свойств и обработчиков событий).
Но при этом ты теряешь:
1) все события связанные с созданием/отображением/закрытием формы и т.п.
2) возможность обращаться из обработчиков событий к переменным формы непосредственно, так как экземпляр элементов управления ИНЫЕ и по названиям переменных доступны не будут.
Т.е. возможное решение:
— создавать скрытый экзепляр формы или читать ее описание из ресурсов (можно, но как не помню, где-то статью видел, кажется).
— кодить ВСЕ обработчики аккуратно в предположении, что тебе доступны ТОЛЬКО те значения и объекты, которые тебе переданы в обработчик явно через его параметры.
P.S. Кстати, спасибо за идею. Возможно что-то похожее для себя буду использовать, только лень было возиться с полностью ручным рисованием формы. А вот нарисовать форму и загрузить ее в панельку — это другое дело.
P.P.S. В одном проекте мы извратились для этой же цели так: положили на форму TabbedPanel и Panel. В процессе написания программы ты с помощью TabbedPanel все очень мило настраиваешь, а при выполнении программы все элементы управления "перепрыгивают" на Panel. Работало нормально, только что-то мне этот подход разонравился. Была только одна проблема — размер поля для контролов в TabbedPanel меньше (по вертикали), чем в обычном Panel, поэтому приходилось расположение элементов тчательно перепроверять.
Здравствуйте, Рома, Вы писали:
Р>Можно воспользоваться обычным PageControl, спрятав закладки и в зависимости от чегото переключать их програмно. Получается очень интересно !
Ага, ооочень интересно... Только миргает и мигает достаточно заметно при прятании одной страницы и показе другой... Уж лучше несколько TPanel и для каждой для показа вызывать BringToFront().
А лучше всего, как сказал Sinclair — юзать TFrame.
Здравствуйте, Flamer, Вы писали:
F>Здравствуйте, Рома, Вы писали:
F>Ага, ооочень интересно... Только миргает и мигает достаточно заметно при прятании одной страницы и показе другой... Уж лучше несколько TPanel и для каждой для показа вызывать BringToFront().
А ты уверен, что панели моргать и мигать не будут(особенно когда на них куча всего)! Ты попробуй ! А вот если правильно "Лочить" update окна то все выходит достойно и можно пользоваться PageControl. F>А лучше всего, как сказал Sinclair — юзать TFrame.
А может еще более извратится и ActiveForm присандалить?
Внимательность, внимательность и еще раз ..... забыл, про что я?
Здравствуйте, Рома, Вы писали: F>>А лучше всего, как сказал Sinclair — юзать TFrame. Р>А может еще более извратится и ActiveForm присандалить?
А вот этого не надо. Поясняю: TFrame сделан специально для того, чтобы можно было дизайнить форму отдельно, а потом встраивать ее в другую.
Это позволит сделать модель расширяемой.
Всякие невидимые табы с копированием контролов делают тоже самое, только через... другой вход.
Делать модель нерасширяемой можно при помощи просто набора панелей, которые хайдятся/показываются (см. пост Flamerа)
ActiveForm в данном контексте является избыточным решением.
... << RSDN@Home 1.0 beta 6 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>ActiveForm в данном контексте является избыточным решением.
По поводу Frame"ов я полностью с Вами согласен! Но для кол-ва вариантов отображенияы < 3 очень удобно пользоваться PageControl.
По поводу ЭктивФорм скажу, что очень удобно использовать в случаях, когда тебуется поменять вид и логику без компиляции проэкта.
А для достижения OutLook"оподобности советую пользоваться компонентами DeveloperExpress. Полная копия + очень много доп. возможностей + простота настройки и использования. Лучше этих компонент ничего не видел.
См. здесь о возможностях компонент! Просто улет. С выходом 4 версии ничего нет невозможного!
Внимательность, внимательность и еще раз ..... забыл, про что я?
Здравствуйте, Рома, Вы писали: Р>А для достижения OutLook"оподобности советую пользоваться компонентами DeveloperExpress. Полная копия + очень много доп. возможностей + простота настройки и использования. Лучше этих компонент ничего не видел.
Знаем таких. Рулят ребята. Хорошо поработали.
... << RSDN@Home 1.0 beta 6 >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, mikkri, Вы писали:
M>Признаю, извратились мы без оснований . Для тех же целей можно было использовать TFrame.
Вспомнил! Основания все же были.
Часть элементов управления нужно было отображать всегда, а остальные в зависимости от выбранного условия. Причем те, что отображались всегда, нужно было органично отображать среди тех, что отображались в зависимости от условия.
////////////////////unit mkkClassPlacer;
interface
uses
Windows, Messages, SysUtils, Classes, Controls, Forms, ExtCtrls, contnrs;
type
EmkkException = class(Exception)
end;{TmkkException}
{TmkkControlClass}
TmkkControlClass = class of TWinControl;
{TmkkOnErrorEvent}
TmkkErrorEvent = procedure(Sender: TObject; AClass: TmkkControlClass; AError: EmkkException; var ADoAbort: boolean) of object;
TmkkPlacerChangeEvent = procedure (NewControl, OldControl: TWinControl) of object;
{TmkkClassStack}
TmkkClassStack = class(TClassList)
function Pop: TClass;
function Push(AClass: TClass): Integer;
function IsEmpty: Boolean;
function Peek: TClass;
end;{TmkkClassStack}
{TmkkClassPlacer}
TmkkClassPlacer = class(TCustomPanel)
private
FIncludeList: boolean;
FAlignClass: TAlign;
FBackClasses: TmkkClassStack;
FNextClasses: TmkkClassStack;
FInplaceClass: TmkkControlClass;
FInplaceControl: TWinControl;
FRemoveFormBorders: Boolean;
FOnError: TmkkErrorEvent;
FOnAfterChange: TNotifyEvent;
FOnBeforeChange: TNotifyEvent;
FOnPlacerChange: TmkkPlacerChangeEvent;
function GetEnableBack: Boolean;
function GetEnableNext: Boolean;
procedure SetAlignClass(const Value: TAlign);
procedure SetIncludeList(const Value: boolean);
procedure SetInplaceClass(const Value: TmkkControlClass);
protected
property BackClasses: TmkkClassStack
read FBackClasses;
property NextClasses: TmkkClassStack
read FNextClasses;
procedure AfterChange; virtual;
procedure BeforeChange; virtual;
procedure DoError(AClass: TmkkControlClass; AException: EmkkException; var ADoAbort: Boolean); virtual;
procedure DoPlacerChange(NewControl, OldControl: TWinControl); virtual;
public
property EnableBack: Boolean
read GetEnableBack;
property EnableNext: Boolean
read GetEnableNext;
procedure Next; virtual;
procedure Back; virtual;
procedure ClearNext;
procedure ClearBack;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Align;
property Constraints;
property AlignClass: TAlign
read FAlignClass
write SetAlignClass default alClient;
property BorderStyle;
property BevelInner;
property BevelOuter;
property BorderWidth;
property BevelWidth;
property Color;
property Caption;
property Enabled;
property ShowHint;
property Hint;
property ParentShowHint;
property ParentColor;
property Font;
property InplaceClass: TmkkControlClass
read FInplaceClass
write SetInplaceClass default nil;
property InplaceControl: TWinControl
read FInplaceControl default nil;
property IncludeInList: boolean
read FIncludeList
write SetIncludeList default False;
property RemoveFormBorders: Boolean
read FRemoveFormBorders
write FRemoveFormBorders default True;
property OnAfterChange: TNotifyEvent
read FOnAfterChange
write FOnAfterChange default nil;
property OnBeforeChange: TNotifyEvent
read FOnBeforeChange
write FOnBeforeChange default nil;
property OnError: TmkkErrorEvent
read FOnError
write FOnError default nil;
property OnPlacerChange: TmkkPlacerChangeEvent
read FOnPlacerChange
write FOnPlacerChange default nil;
property OnCanResize;
property OnClick;
property OnConstrainedResize;
property OnContextPopup;
property OnDblClick;
property OnEnter;
property OnExit;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnResize;
end;{TmkkClassPlacer}procedure Register;
implementation
uses mkkConsts;
procedure StackAlreadyEmpty;
begin
raise EmkkException.Create(serrStackEmpty);
end;{StackAlreadyEmpty}procedure Register;
begin
RegisterComponents('Mkk', [TmkkClassPlacer]);
end;
{ TmkkClassStack }function TmkkClassStack.IsEmpty: Boolean;
begin
Result := Count = 0;
end;
function TmkkClassStack.Peek: TClass;
begin
Result := nil;
if not IsEmpty then
Result := Items[(Count-1)];
end;
function TmkkClassStack.Pop: TClass;
var
liIndex: Integer;
begin
Result := nil;
if IsEmpty then
StackAlreadyEmpty;
liIndex:= Count-1;
Result := Items[liIndex];
Delete(liIndex);
end;
function TmkkClassStack.Push(AClass: TClass): Integer;
begin
Result := Add(AClass);
end;
{ TmkkClassPlacer }procedure TmkkClassPlacer.Back;
var
Value: TmkkControlClass;
OldClass :TmkkControlClass;
OldControl: TWinControl;
NewClass: TmkkControlClass;
NewControl: TWinControl;
DoAbort: Boolean;
begin
if not EnableBack then Exit;
NewClass := nil;
NewControl := nil;
Value := TmkkControlClass(FBackClasses.Pop);
if FInplaceClass <> Value then
begin//FInplaceClass := Value;
OldClass := FInplaceClass;
OldControl := FInplaceControl;
if Assigned(Value) then
begin
BeforeChange;
try
NewControl := Value.Create(Self);
NewControl.Parent := self;
NewControl.Align := AlignClass;
if (NewControl is TCustomForm) and (FRemoveFormBorders)then
(NewControl as TCustomForm).BorderStyle := bsNone;
NewControl.Visible := True;
except
on E: Exception do
begin
DoAbort := True;
DoError(Value, (E as EmkkException), DoAbort);
if DoAbort then raise;
end;{on .. do}end;{try .. except}
DoPlacerChange(NewControl, OldControl);
FInplaceControl.Free;
FInplaceControl := NewControl;
FInplaceClass := Value;
if FIncludeList then
begin
if Assigned(OldClass) then
begin
FNextClasses.Push(OldClass);
end;{if .. then}end;{if .. then}
AfterChange;
end{if .. then}end;
end;
procedure TmkkClassPlacer.ClearBack;
begin
FBackClasses.Clear;
end;
procedure TmkkClassPlacer.ClearNext;
begin
FNextClasses.Clear;
end;
constructor TmkkClassPlacer.Create(AOwner: TComponent);
begin
inherited;
FRemoveFormBorders := True;
FBackClasses := TmkkClassStack.Create;
FNextClasses := TmkkClassStack.Create;
FInplaceClass := nil;
FInplaceControl := nil;
IncludeInList := False;
FAlignClass := alClient;
FOnBeforeChange := nil;
FOnAfterChange := nil;
FOnError := nil;
FOnPlacerChange := nil;
end;
destructor TmkkClassPlacer.Destroy;
begin
InplaceClass := nil;
FOnBeforeChange := nil;
FOnAfterChange := nil;
FOnError := nil;
FBackClasses.Free;
FNextCLasses.Free;
inherited;
end;
procedure TmkkClassPlacer.BeforeChange;
begin
if Assigned(FOnBeforeChange) then
FOnBeforeChange(self);
end;
procedure TmkkClassPlacer.DoError;
begin
if Assigned(FOnError) then
FOnError(self, AClass, AException, ADoAbort);
end;
function TmkkClassPlacer.GetEnableBack: Boolean;
begin
Result := FBackClasses.Count <> 0;
end;
function TmkkClassPlacer.GetEnableNext: Boolean;
begin
Result := FNextClasses.Count <> 0;
end;
procedure TmkkClassPlacer.Next;
var
Value: TmkkControlClass;
OldClass :TmkkControlClass;
OldControl: TWinControl;
NewClass: TmkkControlClass;
NewControl: TWinControl;
DoAbort: boolean;
begin
if not EnableNext then Exit;
NewClass := nil;
NewControl := nil;
Value := TmkkControlClass(FNextClasses.Pop);
if FInplaceClass <> Value then
begin//FInplaceClass := Value;
OldClass := FInplaceClass;
OldControl := FInplaceControl;
if Assigned(Value) then
begin
BeforeChange;
try
NewControl := Value.Create(Self);
NewControl.Parent := self;
NewControl.Align := AlignClass;
if (NewControl is TCustomForm) and (FRemoveFormBorders)then
(NewControl as TCustomForm).BorderStyle := bsNone;
NewControl.Visible := True;
except
on E: Exception do
begin
DoAbort := True;
DoError(Value, (E as EmkkException), DoAbort);
if DoAbort then raise;
end;{on .. do}end;{try .. except}
DoPlacerChange(NewControl, OldControl);
FInplaceControl.Free;
FInplaceControl := NewControl;
FInplaceClass := Value;
if FIncludeList then
begin
if Assigned(OldClass) then
begin
FBackClasses.Push(OldClass);
end;{if .. then}end;{if .. then}
AfterChange;
end{if .. then}end;
end;
procedure TmkkClassPlacer.SetAlignClass(const Value: TAlign);
begin
if FAlignClass <> Value then
begin
FAlignClass := Value;
if Assigned(FInplaceControl) then
FInplaceControl.Align := Value;
end;{if .. then}end;
procedure TmkkClassPlacer.SetIncludeList(const Value: boolean);
begin
if FIncludeList <> Value then
FIncludeList := Value;
end;
procedure TmkkClassPlacer.SetInplaceClass(const Value: TmkkControlClass);
var
OldClass :TmkkControlClass;
OldControl: TWinControl;
NewClass: TmkkControlClass;
NewControl: TWinControl;
DoAbort: Boolean;
begin
NewClass := nil;
NewControl := nil;
if FInplaceClass <> Value then
begin//FInplaceClass := Value;
OldClass := FInplaceClass;
OldControl := FInplaceControl;
BeforeChange;
if Assigned(Value) then
begin
try
NewControl := Value.Create(Self);
NewControl.Parent := self;
NewControl.Align := AlignClass;
if (NewControl is TCustomForm) and (FRemoveFormBorders)then
(NewControl as TCustomForm).BorderStyle := bsNone;
NewControl.SendToBack;
NewControl.Visible := True;
except
on E: Exception do
begin
DoAbort := True;
DoError(Value, (E as EmkkException), DoAbort);
if DoAbort then raise;
end;{on .. do}end;{try .. except}
DoPlacerChange(NewControl, OldControl);
FInplaceControl.Free;
FInplaceControl := NewControl;
FInplaceClass := Value;
FNextClasses.Clear;
if FIncludeList then
begin
if Assigned(OldClass) then
begin
FBackClasses.Push(OldClass);
end;{if .. then}end;{if .. then}
NewControl.BringToFront;
AfterChange;
end{if .. then}end;
end;
procedure TmkkClassPlacer.AfterChange;
begin
if Assigned(FOnAfterChange) then
FOnAfterChange(self);
end;
procedure TmkkClassPlacer.DoPlacerChange(NewControl,
OldControl: TWinControl);
begin
if Assigned(FOnPlacerChange) then
FOnPlacerChange(NewControl, OldControl);
end;
end.
/////////////
Устанавливаем сию хрень в палитру.
Пример использования
Кидаем на форму TmkkClassPlacer — получаем область в которой будут отображаться формы или фреймы.
Создаем формы которые надо отображать кидаем на них компоненты, убираем из списка Auto-Create Forms. Подключаем модули с формами к модулю с TmkkClassPlacer.
Для того чтобы отобразить нужную форму используем следующее
mkkClassPlacer1.InplaceClass := <класс формы>
например
mkkClassPlacer1.InplaceClass := TForm1; — создает отображает форму Form1
.....
mkkClassPlacer1.InplaceClass := TForm2;- создает отображает форму Form2
.....
mkkClassPlacer1.InplaceClass := nil; — удаляет текущую созданую форму
через mkkClassPlacer1.InplaceControl — получаем доступ к созданой форме.
........
Если необходимо сохранять состояние формы, то лучьше воспользоватся TMergeManager из RxLib
Если нужен пример мыльте