Solved

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

Posted on 2009-06-30
7
367 Views
Last Modified: 2013-12-04
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
0
Comment
Question by:PTRUSCOTT
  • 5
7 Comments
 
LVL 14

Accepted Solution

by:
SteveBay earned 125 total points
ID: 24745329
In Delphi visual components are typically considered public to the form, Therefore it is considered normal and acceptable to do things like this:
procedure TForm1.Button1Click(Sender: TObject);

var StrVal : String;

begin

     StrVal := '';

     Form2 := TForm2.Create(nil);

     if Form2.ShowModal = mrOK then

          StrVal := Form2.Edit1.Text;

     FreeAndNil(Form2);

     ShowMessage(StrVal);

end;

Open in new window

0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 24745357
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

0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 24745384
use it like this from a other form:

procedure TFormX.btnSelectMailsClick(Sender: TObject);
begin
  Memo1.Lines.Delimiter := ';';
  Memo1.Lines.DelimitedText := SelectEmails(Self);
end;
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 24745397
0
 
LVL 22

Expert Comment

by:8080_Diver
ID: 24746148
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).
0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 24751603
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

0
 
LVL 36

Expert Comment

by:Geert Gruwez
ID: 24753640
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

0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

zlib is a free compression library (a DLL) on which the popular gzip utility is built.  In this article, we'll see how to use the zlib functions to compress and decompress data in memory; that is, without needing to use a temporary file.  We'll be c…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now