Link to home
Start Free TrialLog in
Avatar of PTRUSCOTT
PTRUSCOTT

asked on

How to communicate date from a Child Form to a Parent Form in Delphi 7

Dear Experts,

When I was programming in Visual C++ I would sometimes use very bad techniques to move data from a child dialog box to the window that calls it.  Let's suppose I have a dialog box that shows a list of items in a single column grid.  When the user double clicks on an item, that item is selected and the dialog box closes, returning control to the parent window.

            In C++ I could get text from an edit field with a command like this:
      form_edit.GetWindowText(answer_string,sizeof(answer_string));

In this case the variable answer_string would be a global variable so the user's selection would be available, through the global variable, to the parent window that called the dialog box.

I realize it is considered bad programming to have too many global variables.  What is the proper way to transfer data in this situation?  After double-clicking my dialog box shuts down so the user's answer has to be stored somewhere before the dialog box's memory is freed.  

How do I cleanly shut down the dialog box?  In C++, I could use this command:

      CDialog::OnOK();

What is the proper way to do this in Delphi?
Sincerely,

Phil Truscott
ASKER CERTIFIED SOLUTION
Avatar of SteveBay
SteveBay
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
depends what you want to get as return value
is it only 1 value ? -> use a function
is it more 1 value, with a check -> use a function with a out parameter
is it more than 1 value -> use a TStrings or Dataset

this is a sample of returning the selected email adresses in a string field
you could get the separate emails out again using the delimitedtext from TStrings
unit Unit2;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, StdCtrls, Buttons, ExtCtrls, Grids, DBGrids, DBClient;
 
type
  TfrmSelectEmails = class(TForm)
    cds: TClientDataSet;
    ds: TDataSource;
    grid: TDBGrid;
    pnl: TPanel;
    btnCancel: TBitBtn;
    btnSelectAll: TBitBtn;
    btnOk: TBitBtn;
    cdsName: TStringField;
    cdsemail: TStringField;
    procedure btnSelectAllClick(Sender: TObject);
  private
    function GetSelectedEmails: string;
    procedure SelectAll;
    procedure RandomData;
  public
    constructor Create(AOwner: TComponent); override;
    property SelectedEmails: string read GetSelectedEmails;
  end;
 
var
  frmSelectEmails: TfrmSelectEmails;
 
function SelectEmails(AOwner: TComponent): string;
 
implementation
 
{$R *.dfm}
 
function SelectEmails(AOwner: TComponent): string;
begin
  Result := '';
  frmSelectEmails := TfrmSelectEmails.Create(AOwner);
  try
    if frmSelectEmails.ShowModal = mrOk then
      Result := frmSelectEmails.SelectedEmails;
  finally
    FreeAndNil(frmSelectEmails);
  end;
end;
 
{ TfrmSelectEmails }
 
procedure TfrmSelectEmails.btnSelectAllClick(Sender: TObject);
begin
  SelectAll;
end;
 
constructor TfrmSelectEmails.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  cds.Active := True;
  RandomData;
end;
 
function TfrmSelectEmails.GetSelectedEmails: string;
const Delimiter = ';';
var b: TBookmark;
begin
  Result := '';
  with grid.DataSource.DataSet do
  begin
    DisableControls;
    try
      b := GetBookmark;
      try
        First;
        while not Eof do
        begin
          if grid.SelectedRows.CurrentRowSelected then
            Result := Result + FieldByName('email').AsString + Delimiter;
          Next;
        end;
      finally
        GotoBookmark(b);
        FreeBookmark(b);
      end;
    finally
      EnableControls;
    end;
  end;
  if Result <> '' then
    Delete(Result, Length(Result) - Length(Delimiter) + 1, Length(Delimiter));
end;
 
procedure TfrmSelectEmails.RandomData;
const MaxRandom = 30;
var I: Integer;
begin
  for I := 0 to Random(MaxRandom) do
    cds.InsertRecord([Format('name ', [i]), Format('email%d@abc.com', [i])]);
end;
 
procedure TfrmSelectEmails.SelectAll;
var b: TBookmark;
begin
  grid.SelectedRows.Clear;
  with grid.DataSource.DataSet do
  begin
    DisableControls;
    try
      b := GetBookmark;
      try
        First;
        while not Eof do
        begin
          grid.SelectedRows.CurrentRowSelected := True;
          Next;
        end;
      finally
        GotoBookmark(b);
        FreeBookmark(b);
      end;
    finally
      EnableControls;
    end;
  end;
end;
 
end.
 
--- dfm ---
object frmSelectEmails: TfrmSelectEmails
  Left = 0
  Top = 0
  Caption = 'Select emails'
  ClientHeight = 451
  ClientWidth = 692
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object grid: TDBGrid
    Left = 0
    Top = 0
    Width = 692
    Height = 392
    Align = alClient
    DataSource = ds
    Options = [dgEditing, dgTitles, dgIndicator, dgColumnResize, dgColLines, dgRowLines, dgTabs, dgConfirmDelete, dgCancelOnExit, dgMultiSelect]
    TabOrder = 0
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'Tahoma'
    TitleFont.Style = []
  end
  object pnl: TPanel
    Left = 0
    Top = 392
    Width = 692
    Height = 59
    Align = alBottom
    TabOrder = 1
    object btnCancel: TBitBtn
      Left = 568
      Top = 16
      Width = 105
      Height = 25
      DoubleBuffered = True
      Kind = bkCancel
      ParentDoubleBuffered = False
      TabOrder = 0
    end
    object btnSelectAll: TBitBtn
      Left = 16
      Top = 16
      Width = 105
      Height = 25
      Caption = 'Select All'
      DoubleBuffered = True
      Glyph.Data = {
        F2010000424DF201000000000000760000002800000024000000130000000100
        0400000000007C01000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333334433333
        3333333333388F3333333333000033334224333333333333338338F333333333
        0000333422224333333333333833338F33333333000033422222243333333333
        83333338F3333333000034222A22224333333338F33F33338F33333300003222
        A2A2224333333338F383F3338F33333300003A2A222A222433333338F8333F33
        38F33333000034A22222A22243333338833333F3338F333300004222A2222A22
        2433338F338F333F3338F3330000222A3A2224A22243338F3838F338F3338F33
        0000A2A333A2224A2224338F83338F338F3338F300003A33333A2224A2224338
        333338F338F3338F000033333333A2224A2243333333338F338F338F00003333
        33333A2224A2233333333338F338F83300003333333333A2224A333333333333
        8F338F33000033333333333A222433333333333338F338F30000333333333333
        A224333333333333338F38F300003333333333333A223333333333333338F8F3
        000033333333333333A3333333333333333383330000}
      NumGlyphs = 2
      ParentDoubleBuffered = False
      TabOrder = 1
      OnClick = btnSelectAllClick
    end
    object btnOk: TBitBtn
      Left = 440
      Top = 16
      Width = 105
      Height = 25
      DoubleBuffered = True
      Kind = bkOK
      ParentDoubleBuffered = False
      TabOrder = 2
    end
  end
  object cds: TClientDataSet
    Active = True
    Aggregates = <>
    Params = <>
    Left = 576
    Top = 40
    Data = {
      4D0000009619E0BD0100000018000000020000000000030000004D00044E616D
      65010049000000010005574944544802000200640005656D61696C0200490000
      000100055749445448020002002C010000}
    object cdsName: TStringField
      FieldName = 'Name'
      Size = 100
    end
    object cdsemail: TStringField
      FieldName = 'email'
      Size = 300
    end
  end
  object ds: TDataSource
    DataSet = cds
    Left = 512
    Top = 40
  end
end

Open in new window

use it like this from a other form:

procedure TFormX.btnSelectMailsClick(Sender: TObject);
begin
  Memo1.Lines.Delimiter := ';';
  Memo1.Lines.DelimitedText := SelectEmails(Self);
end;
I have an approach that I learned from a Certified Delphi Instructor Instructor (i.e. he taught the guys who taught Delphi ;-).  
In the unit of forms (other than the mainform), I have a completely public function.  (For instance, I have a standard AboutBox form that I use and the function that it has for displaying the AboutBox is called TellAbout.)  This function (which, as in the case of my AboutBox, can be over loaded to allow various options), expects to receive certain paramaters which may be passed as constants and/or , as variables.  This function then creates the form, fills in any appropriate variables specific to the form, and shows the form (usually, I use ShowModal).  When the user closes the form, the function will extract any information from the form that should be returned to the calling form and then releases the form.  Also, I generally use a TModalResult for the return value from the function and that means I can use the result from the user closing the form, if aI want to.
By putting this function in the form's unit, you don't have to code the set up, show, and data extraction every place that you want to call the form . . . you just do another function call.  It also means that the form/unit is not tightly coupled to the other units in the application and, therefore, it contributes to code reusability (both within and between applications).  Finally, since you can over load the function, you can add new parameters for specific applications/calls and, by not requiring them in the old function call (which you leave in the unit), you don't break the contract with any existing applications/calls.
Effectively, you can pass the parameters to the function and receive results back in the parameters and easily solve your problem.
If you want, I can provide you with my AboutBox as an example of the process (it has 2 variations on the TellAbout function).
8080_Diver,
i don't often consider the overloading but using my previous sample ...

this instructor ... looks like he does the same as i do
unit Unit2;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, StdCtrls, Buttons, ExtCtrls, Grids, DBGrids, DBClient;
 
type
  TfrmSelectEmails = class(TForm)
    cds: TClientDataSet;
    ds: TDataSource;
    grid: TDBGrid;
    pnl: TPanel;
    btnCancel: TBitBtn;
    btnSelectAll: TBitBtn;
    btnOk: TBitBtn;
    cdsName: TStringField;
    cdsemail: TStringField;
    procedure btnSelectAllClick(Sender: TObject);
  private
    function GetSelectedEmails: string;
    procedure SelectAll;
    procedure RandomData;
  public
    constructor Create(AOwner: TComponent); override;
    property SelectedEmails: string read GetSelectedEmails;
  end;
 
var
  frmSelectEmails: TfrmSelectEmails;
 
function SelectEmails(AOwner: TComponent): string; overload;
procedure SelectEmails(AOwner: TComponent; var Emails: string); overload;
 
 
implementation
 
{$R *.dfm}
 
function SelectEmails(AOwner: TComponent): string;
begin
  Result := '';
  frmSelectEmails := TfrmSelectEmails.Create(AOwner);
  try
    if frmSelectEmails.ShowModal = mrOk then
      Result := frmSelectEmails.SelectedEmails;
  finally
    FreeAndNil(frmSelectEmails);
  end;
end;
 
procedure SelectEmails(AOwner: TComponent; var Emails: string); 
begin
  Emails := SelectEmails(AOwner);
end;
 
{ TfrmSelectEmails }
 
procedure TfrmSelectEmails.btnSelectAllClick(Sender: TObject);
begin
  SelectAll;
end;
 
constructor TfrmSelectEmails.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  cds.Active := True;
  RandomData;
end;
 
function TfrmSelectEmails.GetSelectedEmails: string;
const Delimiter = ';';
var b: TBookmark;
begin
  Result := '';
  with grid.DataSource.DataSet do
  begin
    DisableControls;
    try
      b := GetBookmark;
      try
        First;
        while not Eof do
        begin
          if grid.SelectedRows.CurrentRowSelected then
            Result := Result + FieldByName('email').AsString + Delimiter;
          Next;
        end;
      finally
        GotoBookmark(b);
        FreeBookmark(b);
      end;
    finally
      EnableControls;
    end;
  end;
  if Result <> '' then
    Delete(Result, Length(Result) - Length(Delimiter) + 1, Length(Delimiter));
end;
 
procedure TfrmSelectEmails.RandomData;
const MaxRandom = 30;
var I: Integer;
begin
  for I := 0 to Random(MaxRandom) do
    cds.InsertRecord([Format('name ', [i]), Format('email%d@abc.com', [i])]);
end;
 
procedure TfrmSelectEmails.SelectAll;
var b: TBookmark;
begin
  grid.SelectedRows.Clear;
  with grid.DataSource.DataSet do
  begin
    DisableControls;
    try
      b := GetBookmark;
      try
        First;
        while not Eof do
        begin
          grid.SelectedRows.CurrentRowSelected := True;
          Next;
        end;
      finally
        GotoBookmark(b);
        FreeBookmark(b);
      end;
    finally
      EnableControls;
    end;
  end;
end;
 
end.
 
--- dfm ---
object frmSelectEmails: TfrmSelectEmails
  Left = 0
  Top = 0
  Caption = 'Select emails'
  ClientHeight = 451
  ClientWidth = 692
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object grid: TDBGrid
    Left = 0
    Top = 0
    Width = 692
    Height = 392
    Align = alClient
    DataSource = ds
    Options = [dgEditing, dgTitles, dgIndicator, dgColumnResize, dgColLines, dgRowLines, dgTabs, dgConfirmDelete, dgCancelOnExit, dgMultiSelect]
    TabOrder = 0
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'Tahoma'
    TitleFont.Style = []
  end
  object pnl: TPanel
    Left = 0
    Top = 392
    Width = 692
    Height = 59
    Align = alBottom
    TabOrder = 1
    object btnCancel: TBitBtn
      Left = 568
      Top = 16
      Width = 105
      Height = 25
      DoubleBuffered = True
      Kind = bkCancel
      ParentDoubleBuffered = False
      TabOrder = 0
    end
    object btnSelectAll: TBitBtn
      Left = 16
      Top = 16
      Width = 105
      Height = 25
      Caption = 'Select All'
      DoubleBuffered = True
      Glyph.Data = {
        F2010000424DF201000000000000760000002800000024000000130000000100
        0400000000007C01000000000000000000001000000000000000000000000000
        80000080000000808000800000008000800080800000C0C0C000808080000000
        FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333334433333
        3333333333388F3333333333000033334224333333333333338338F333333333
        0000333422224333333333333833338F33333333000033422222243333333333
        83333338F3333333000034222A22224333333338F33F33338F33333300003222
        A2A2224333333338F383F3338F33333300003A2A222A222433333338F8333F33
        38F33333000034A22222A22243333338833333F3338F333300004222A2222A22
        2433338F338F333F3338F3330000222A3A2224A22243338F3838F338F3338F33
        0000A2A333A2224A2224338F83338F338F3338F300003A33333A2224A2224338
        333338F338F3338F000033333333A2224A2243333333338F338F338F00003333
        33333A2224A2233333333338F338F83300003333333333A2224A333333333333
        8F338F33000033333333333A222433333333333338F338F30000333333333333
        A224333333333333338F38F300003333333333333A223333333333333338F8F3
        000033333333333333A3333333333333333383330000}
      NumGlyphs = 2
      ParentDoubleBuffered = False
      TabOrder = 1
      OnClick = btnSelectAllClick
    end
    object btnOk: TBitBtn
      Left = 440
      Top = 16
      Width = 105
      Height = 25
      DoubleBuffered = True
      Kind = bkOK
      ParentDoubleBuffered = False
      TabOrder = 2
    end
  end
  object cds: TClientDataSet
    Active = True
    Aggregates = <>
    Params = <>
    Left = 576
    Top = 40
    Data = {
      4D0000009619E0BD0100000018000000020000000000030000004D00044E616D
      65010049000000010005574944544802000200640005656D61696C0200490000
      000100055749445448020002002C010000}
    object cdsName: TStringField
      FieldName = 'Name'
      Size = 100
    end
    object cdsemail: TStringField
      FieldName = 'email'
      Size = 300
    end
  end
  object ds: TDataSource
    DataSet = cds
    Left = 512
    Top = 40
  end
end

Open in new window

ow i see you need a date ... i thought you meant data
you could do this with a boolean and a TDateTime type
and TDateTime


unit uSelectDate;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, Buttons, ExtCtrls;
 
type
  TfrmDatePick = class(TForm)
    pnlButtons: TPanel;
    btnOk: TBitBtn;
    btnCancel: TBitBtn;
    mcPick: TMonthCalendar;
  end;
 
var
  frmDatePick: TfrmDatePick;
 
function SelectDate(AOwner: TComponent; var ADate: TDateTime): Boolean;
 
implementation
 
{$R *.dfm}
 
function SelectDate(AOwner: TComponent; var ADate: TDateTime): Boolean;
var frm: TfrmDatePick;
begin
  Result := False;
  frm := TfrmDatePick.Create(AOwner);
  try
    if frm.ShowModal = mrOk then
    begin
      Result := True;
      ADate := frm.mcPick.Date;
    end;
  finally
    FreeAndNil(frm);
  end;
end;
 
end.

Open in new window