Solved

MDI Windows needing separate values

Posted on 1998-10-10
3
193 Views
Last Modified: 2010-04-03

I have an MDI application.  On the menu, one of the buttons is to open a window where
the user can enter SQL.  I WANT TO ALLOW MULTIPLE COPIES OF THIS WINDOW TO BE OPEN.
Here's the code:

-------------------------------------------------------------
procedure TMainForm.SQLWindow1Click(Sender: TObject);
var
  Child: TSQL_F;
begin
  { create a new MDI child window }
    Child := TSQL_F.Create(Application);
end;

// THIS CODE APPEARS TO WORK FINE.  IT OPENS A NEW WINDOW EACH TIME I CLICK THE MENU

--------------------------------------------------------------

The SQL Window can have one of three different datamodule attached to it.  I do this
with pointers.

Here is the various code fragments:
---------------------------------------------------------------
unit SQL_Form;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ...


type
  TSQL_F = class(TForm)
    ExecuteBtn: TBitBtn;
    ...
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


var {Global Variables }
  SQL_F          : TSQL_F;
  Row            : Integer;

implementation


uses Delete_Explain_Form, Oracle_DataMod1, Main, DataModStuff;

Var {Local Variables }
 
 First_Time : Boolean;
 ThisWindow : TSQL_F;
 ActiveDataMod: ^TDataModule;  // Pointer to the datamodule that this window is using



{$R *.DFM}

-----------------------------------------------------------------------

The problem that I am having is that the pointer to the datamodule works if I only
have ONE window.  I can open one window and close one window, everything is fine.
Here's the problem scenario:  

Open first copy of window
Open second copy of window
Close one of these windows
Close the second window - APP BLOWS UP HERE

-- Let me walk you through the process of how I create the pointer

-----------   in the ONCREATE ROUTINE

// Now Create the Pointer to the Active Data Module;
// This simply allocates memory for the pointer
New(ActiveDataMod);



-----------   In the ONACTIVATE ROUTINE

{if this is the FIRST TIME THIS ROUTINE IS RUN}

If New_Connection_No = 1 then
      ActiveDataMod^ := Oracle_DM1;   //Oracle_DM1 is a data module that is already created

If New_Connection_No = 2 then
      ActiveDataMod^ := Oracle_DM2;

If New_Connection_No = 3 then
      ActiveDataMod^ := Oracle_DM3;


// Set up the Direct Oracle Access parameters
ThisWindow.OraclewwDataSet1.Session := (ActiveDataMod^ as TOracle_DM1).OracleSession1;
ThisWindow.OracleQuery1.Session := (ActiveDataMod^ as TOracle_DM1).OracleSession1;


// THIS CODE APPEARS TO WORK FINE.  I CAN CHANGE CONNECTIONS AS NEEDED

-------------------------------------------------------------------------------


// HERE IS WHERE I HAVE PROBLEMS

procedure TSQL_F.FormClose(Sender: TObject; var Action: TCloseAction);
begin

// Now Free the Pointer to the Active Data Module;
// This simply de-allocates memory for the pointer
Dispose(ActiveDataMod);  // THIS IS WHERE IT BLOWS UP IF I HAVE MULTIPLE COPIES

// Needed to close an MDI Window
Action := caFree;
end;

----------------------------------------------------------------------------


It seems like I only have one ActiveDataMod^.  When debugging, and I close the first window,
ActiveDataMod^ = $F3938C.  I close the window.  When I close the second window, the
ActiveDataMod^ has the same value.  That value, i.e location, i.e pointer, no longer
exists.  This leads me back to the first statement, it seems like I only have one
ActiveDataMod pointer that is SHARED between copied of the MDI window.  But shouldn't each copy of this MDI window have it's OWN variables, specifically the same variables, but each window having it's own SEPARATE, different values for those windows?

What am I doing wrong? Do I have something wrong with scoping.  What I think are local variables are really global variables???

Thanks
George Spears
0
Comment
Question by:gspears060598
3 Comments
 
LVL 5

Expert Comment

by:inter
ID: 1342455
Hi, I think the confusion is that you have a pointer to an object which you allocate. No need to to this since you have already created data modules. So add
ActiveDataMod : TDataModule;
to your protected fields of TSQL_F. And do not create it. It already creates one instance for each of your MDI child windows. So remove all the pointer dereferencing ^ symbols and run-do not dispose it either-
regards, igor
0
 
LVL 4

Accepted Solution

by:
dwwang earned 70 total points
ID: 1342456
I bet you are a C/C++ programmer before -- since I had made such
kind of mistakes and I am a C++ programmer before :)

In Delphi/Object Pascal, components such as TDatamodule are
already POINTERS, so you should never declare pointer of them and
use as in C/C++.

You should do like this:

1. ActiveDataMod: TDataModule;
   (in replace of your: ActiveDataMod: ^TDataModule)

and

2. If New_Connection_No = 1 then
          ActiveDataMod := Oracle_DM1;
(inreplace of you :
              If New_Connection_No = 1 then
                     ActiveDataMod^ := Oracle_DM1; )

3. You never need new() and dispose of those objects.
0
 

Author Comment

by:gspears060598
ID: 1342457
That did the trick...  and you're right <sheepish grin> I am a non-professional C programmer...

Thanks

0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

760 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

23 Experts available now in Live!

Get 1:1 Help Now