Re: Навеяно Outlook-ом
От: №One.  
Дата: 01.03.03 13:49
Оценка:
////////////////////
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
Если нужен пример мыльте
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.