Reputation: 469
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:
and here the detail frame:
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
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