Focus control in the frame
Hopefully I can explain what exactly the problem I am trying to solve. I have a form with 3 folders: 1 for buttons, 1 for data, and 1 for messages. The data pane is populated with some frames (one for each database table I need to use). The section of the table and the other used to display the record in the grid are controlled using the interface.
Here's the mesh frame:
unit FraEdtList;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.Grids, Vcl.DBGrids;
type
TFraEdtLst = class(TFrame)
grdEditori: TDBGrid;
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.dfm}
uses database;
end.
and here's a detailed shot:
unit FraEdtDetail;
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;
type
TFraEdtDtl = class(TFrame)
lblIdEditore: TLabel;
edtIdEditore: TDBEdit;
lblDscEditore: TLabel;
edtDscEditore: TDBEdit;
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.dfm}
uses database;
{ TFraEdtDtl }
{ TFraEdtDtl }
end.
Here is the interface:
unit Editori;
interface
uses
FraEdtList, FraEdtDetail;
type
IEditori = interface
procedure CreateFraEdtLst();
procedure CreateFraEdtDtl();
end;
TEditori = class(TInterfacedObject, IEditori)
private
FEdtLst: TfraEdtLst;
FEdtDtl: TfraEdtDtl;
procedure CreateFraEdtLst();
procedure CreateFraEdtDtl();
end;
implementation
{ TAutori }
uses Tabelle;
procedure TEditori.CreateFraEdtLst;
begin
FEdtLst := FEdtLst.Create(frmTabelle);
FEdtLst.Parent := frmTabelle.pnlDta;
end;
procedure TEditori.CreateFraEdtDtl;
begin
FEdtDtl := TfraEdtDtl.Create(frmTabelle);
FEdtDtl.Parent := frmTabelle.pnlDta;
end;
end.
I've added an Editor block to the form that will use frames. In this example, I have not used a grid, but only a detail frame, and when the user selects a table, the records are displayed like the following example:
For example, the first button (with blank paper) is used to insert a new record into my database table, the second is used to edit the currently displayed record, etc.
I would like to focus the DBEdit component when the user clicks the "new" button or the "edit" button, but I cannot achieve this way of working.
Here is a source for using two frames (and some others)
unit Tabelle;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.ExtCtrls, RzPanel, dxBevel, Vcl.Buttons, PngSpeedButton, Autori,
Editori, DBInterface, DbImplementation, MSAccess;
type
TfrmTabelle = class(TForm)
pnlCmd: TRzPanel;
pnlDta: TRzPanel;
pnlMsg: TRzPanel;
bvlCmd: TdxBevel;
bvlNav: TdxBevel;
btnNew: TPngSpeedButton;
btnEdit: TPngSpeedButton;
btnSave: TPngSpeedButton;
btnDelete: TPngSpeedButton;
btnUndo: TPngSpeedButton;
btnPrior: TPngSpeedButton;
btnNext: TPngSpeedButton;
procedure FormCreate(Sender: TObject);
procedure btnNewClick(Sender: TObject);
procedure btnSaveClick(Sender: TObject);
procedure btnPriorClick(Sender: TObject);
procedure btnNextClick(Sender: TObject);
procedure btnEditClick(Sender: TObject);
procedure btnDeleteClick(Sender: TObject);
procedure btnUndoClick(Sender: TObject);
private
FDBTable: IDBTable;
FAutori: IAutori;
FEditori: IEditori;
public
procedure SetButtonsStatus(stsNew, stsEdit, stsSave, stsDelete, stsUndo, stsPnlDta: Boolean);
procedure SetTableName(Table: TMSTable);
end;
var
frmTabelle: TfrmTabelle;
implementation
{$R *.dfm}
{ TfrmTabelle }
{ Inizializzazione }
procedure TfrmTabelle.FormCreate(Sender: TObject);
begin
FDBTable := TDBtable.Create;
end;
{ Impostazione tabella di lavoro }
procedure TfrmTabelle.SetTableName(Table: TMSTable);
begin
FDBTable.DBTable := Table;
SetButtonsStatus(True, True, False, True, False, False);
// Tabella autori
if Table.TableName = 'Autori' then begin
if not Assigned(FAutori) then begin
FAutori := TAutori.Create;
FAutori.CreateFraAutDtl;
end;
end;
// Tabella editori
if Table.TableName = 'Editori' then begin
if not Assigned(FEditori) then begin
FEditori := TEditori.Create;
FEditori.CreateFraEdtDtl;
end;
end;
end;
{ Impostazione pulsanti }
procedure TfrmTabelle.SetButtonsStatus(stsNew, stsEdit, stsSave, stsDelete, stsUndo, stsPnlDta: Boolean);
var
flgTblEmpty: Boolean;
begin
flgTblEmpty := FDBTable.TableIsEmpty;
btnNew.Enabled := stsNew;
btnEdit.Enabled := stsEdit and not flgTblEmpty;
btnSave.Enabled := stsSave;
btnDelete.Enabled := stsDelete and not flgTblEmpty;
btnUndo.Enabled := stsUndo;
pnlDta.Enabled := stsPnlDta;
end;
{ Inserimento nuovo record }
procedure TfrmTabelle.btnNewClick(Sender: TObject);
begin
if FDBTable.NewRecord then
SetButtonsStatus(False, False, True, False, True, True);
end;
{ Editazione record }
procedure TfrmTabelle.btnEditClick(Sender: TObject);
begin
if FDBTable.EditRecord then
SetButtonsStatus(False, False, True, False, True, True);
end;
{ Salvataggio record }
procedure TfrmTabelle.btnSaveClick(Sender: TObject);
begin
if FDBTable.SaveRecord then
SetButtonsStatus(True, True, False, True, False, False);
end;
{ Cancellazione record }
procedure TfrmTabelle.btnDeleteClick(Sender: TObject);
begin
if FDBTable.DeleteRecord then
SetButtonsStatus(True, True, False, True, False, False);
end;
{ Annulla l'operazione in corso }
procedure TfrmTabelle.btnUndoClick(Sender: TObject);
begin
if FDBTable.UndoRecord then
SetButtonsStatus(True, True, False, True, False, False);
end;
{ Record precedente }
procedure TfrmTabelle.btnPriorClick(Sender: TObject);
begin
if FDBTable.PriorRecord then
SetButtonsStatus(True, True, False, True, False, False);
end;
{ Record successivo }
procedure TfrmTabelle.btnNextClick(Sender: TObject);
begin
FDBTable.NextRecord;
end;
end.
As you can see from the above code, the database is also used through the interface! Hope I was clear in my explanation, but I know the question gets a little more complicated. Can someone please help me?
source to share
The IEditori interface needs to be expanded to provide an external control form with a way to inform the interface what is needed. For example, an interface might have methods like AddingRecord, SavingRecord, ValidateRecord, etc. Then, the parent form doesn't need to be aware of the individual controls in the frame, but the frame can be informed of what's going on and respond correctly by setting focused controls. There may be other things you want to do for the new entry, such as defaults or setting additional state.
You can sometimes parse events directly from the table, such as OnNewRecord, but when you loop the table around, you need to make sure you are not stepping on events that were set elsewhere.
source to share
For example, to focus on edtIdEditore
when the user clicks a button btnEdit
, follow these steps:
{ Editazione record }
procedure TfrmTabelle.btnEditClick(Sender: TObject);
begin
if FDBTable.EditRecord then
SetButtonsStatus(False, False, True, False, True, True);
frmTabelle.edtIdEditore.SetFocus;
end;
Or replace frmTabelle
with the name of the instance of the form provided in var
your device section , then add the device to your proposal uses
and you're done.
source to share