Eros
Eros

Reputation: 469

Delphi frames close form

today my question is (again) about delphi frames. I've an application with a main form and an interface that uses two frames: the first for showing a list of records in a DBGrid and the second for for showing and editing the detail of the selected record. Here the list frame inside the main form:

enter image description here

and here the detail frame:

enter image description here

here is the interface code:

unit TblInterface;

interface

uses
  System.TypInfo, Vcl.Forms, RzPanel, Winapi.Windows, Winapi.Messages,
  UserMessages, Vcl.Dialogs;

type

  TFrameClass = class of TFrame;

  ITabella = interface
  ['{D21924F9-BB41-493B-B06D-0908C0CA73D8}']
    procedure CreateLstFrame(ParentPanel: TRzPanel; Frame: TFrameClass);
    procedure CreateDtlFrame(ParentPanel: TRzPanel; Frame: TFrameClass);
    procedure DestroyLstFrame;
    procedure DestroyDtlFrame;
    procedure BringFrameToFront(FrameType: string);
    procedure OnEditRecord;
  end;

  TTabella = class(TInterfacedObject, ITabella)
  private
    FLst: TFrame;
    FDtl: TFrame;
    procedure CreateLstFrame(ParentPanel: TRzPanel; Frame: TFrameClass);
    procedure CreateDtlFrame(ParentPanel: TRzPanel; Frame: TFrameClass);
    procedure DestroyLstFrame;
    procedure DestroyDtlFrame;
    procedure BringFrameToFront(FrameType: string);
    procedure OnEditRecord;
  end;

implementation

{ TTabella }

{ Creazione foglio lista }
procedure TTabella.CreateLstFrame(ParentPanel: TRzPanel; Frame: TFrameClass);
begin
  FLst := Frame.Create(ParentPanel);
  FLst.Parent := ParentPanel;
end;

{ Creazione form dettaglio }
procedure TTabella.CreateDtlFrame(ParentPanel: TRzPanel; Frame: TFrameClass);
begin
  FDtl := Frame.Create(ParentPanel);
  FDtl.Parent := ParentPanel;
end;

{ Gestione inserimento / modifica record }
procedure TTabella.OnEditRecord;
begin
  SendMessage(FDtl.Handle, WM_EDT_RECORD, 0, 0)
end;

{ Distruzione frame lista }
procedure TTabella.DestroyLstFrame;
begin
  FLst.Free;
end;

{ Distruzione frame dettaglio }
procedure TTabella.DestroyDtlFrame;
begin
  FDtl.Free;
end;

procedure TTabella.BringFrameToFront(FrameType: string);
begin
  if FrameType = 'lst' then
    FLst.BringToFront;
  if FrameType = 'dtl' then
    FDtl.BringToFront;
end;

end.

I can't realize how to make a thing. If the user is on the detail frame and close the main form it will close but I would like, in this case, not to close the form, but to show the list frame.

Here is the source of the list frame:

unit FraAutList;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.Grids, Vcl.DBGrids, UserMessages;

type
  TfraAutLst = class(TFrame)
    grdAutori: TDBGrid;
    procedure grdAutoriDblClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

implementation

{$R *.dfm}

uses database, Tabelle;

procedure TfraAutLst.grdAutoriDblClick(Sender: TObject);
begin
  SendMessage(frmTabelle.Handle, WM_DTL_RECORD, 0, 0)
end;

end.

and here is the source of the detail frame:

unit FraAutDetail;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls, Vcl.Mask, Vcl.DBCtrls, UserMessages;

type
  TFraAutDtl = class(TFrame)
    lblIdAutore: TLabel;
    edtIdAutore: TDBEdit;
    lblCognome: TLabel;
    edtCognome: TDBEdit;
    lblNome: TLabel;
    edtNome: TDBEdit;
  private
    procedure OnEditRecord(var Msg: TMessage); message WM_EDT_RECORD;
  public
    { Public declarations }
  end;

implementation

{$R *.dfm}

uses database;

{ TfraAutDtl }

procedure TFraAutDtl.OnEditRecord(var Msg: TMessage);
begin
  edtCognome.SetFocus;
end;

end.

As you can see I use messages in order to comunicate between frames; for example for showing the detail frame from the list one:

SendMessage(frmTabelle.Handle, WM_DTL_RECORD, 0, 0)

There is a way to avoid the form closure and, instead show the list frame when the user is on the detail frame?

Upvotes: 0

Views: 2431

Answers (1)

ba__friend
ba__friend

Reputation: 5913

Every form has an OnCloseQuery event. Just set the Cancel parameter like this (more or less pseudo code - you would need a function returning the currently shown frame):

Cancel := GetCurrentActiveFrame is TFraAutDtl;
if Cancel then
  PostMessage(GetCurrentActiveFrame.Handle, CM_RELEASE, 0, 0) // or just set Visible := False

The detail frame will close (and free) it self and the previously frame (if there is still one will be shown).

Upvotes: 3

Related Questions