program Project1;uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2},
  Unit3 in 'Unit3.pas' {Form3};{$R *.res}begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
unit Unit1;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;implementationuses Unit2, Unit3;{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.DoForm2;
end;end.unit Unit2;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm2 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure DoForm2;  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form2: TForm2;
implementation
uses Unit3;{$R *.dfm}
procedure TForm2.DoForm2;
var
  Form2: TForm2;
begin
  try
  Application.CreateForm(TForm2, Form2);
    Form2.ShowModal;
  finally
    FreeAndNil(Form2);
  end;
end;procedure TForm2.Button1Click(Sender: TObject);
begin
//
Form3.DoForm3 ;
end;end.unit Unit3;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm3 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure DoForm3;  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form3: TForm3;implementationuses Unit2;{$R *.dfm}procedure TForm3.DoForm3;
var
  Form3: TForm3;
begin  try
  Application.CreateForm(TForm3, Form3);
    Form3.ShowModal;
  finally
    FreeAndNil(Form3);
  end;
end;procedure TForm3.Button1Click(Sender: TObject);
begin
form2.Edit1.Text:='test';
end;end.
思路是,form1弹出form2,form2弹出form3,在form3上得到值,并且给form2上的一个edit1赋值
一切正常,但在form3TForm3.Button1Click(Sender: TObject);出错,内存错误。

解决方案 »

  1.   

    问题在于TForm3.Button1Click事件中引用了Form2.Edit1.Text,在这里面Form2应当指的是全局变量Form2,而在TForm2.DoForm2中也定义了局部变量Form2,函数执行时只是对局部变量赋了值,而全局变量没有赋值,所以在TForm3.Button1Click中引用Form2时就会产生非法访问了。
        这里最简单的解决方法就是把TForm2.DoForm2及TForm3.DoForm3中定义的局局部变量Form2、Form3去掉就可以了。
        之外还可能存在一种隐患,就是在TForm1中调用了Form2.DoForm2而这时Form2并没有得到创建,也会产生非法访问,如果确实需要这样做,可以把Form2.DoForm2定义成类函数,如下:
        class procedure DoForm2;
        不过我觉得对于像显示一个窗体并取得返回值的方法不宜直接这样相互引用,这样做会使得耦合非常乱,可以参考下面这种方法:
      

  2.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementationuses
      Unit2;{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
    begin
      TForm2.DoForm2;
    end;end.
    unit Unit2;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm2 = class(TForm)
        Edit1: TEdit;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        class procedure DoForm2;
      end;var
      Form2: TForm2;implementationuses
      Unit3;{$R *.dfm}class procedure TForm2.DoForm2;
    begin
      with TForm2.Create(Application) do
      try
        ShowModal;
      finally
        Free;
      end;
    end;procedure TForm2.Button1Click(Sender: TObject);
    begin
      Edit1.Text := TForm3.DoForm3;
    end;end.
    unit Unit3;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;type
      TForm3 = class(TForm)
        Label1: TLabel;
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        class function DoForm3: string;
      end;var
      Form3: TForm3;implementation{$R *.dfm}{ TForm3 }class function TForm3.DoForm3: string;
    begin
      with TForm3.Create(Application) do
      try
        ShowModal;
        Result := Label1.Caption;
      finally
        Free;
      end;
    end;procedure TForm3.Button1Click(Sender: TObject);
    begin
      Label1.Caption := IntToStr(random(1000));
    end;end.
      

  3.   

    引用时要特别注意,如在TForm1.ButtonClick中引用的是TForm2.DoForm2,而不是Form2.DoForm2,这是因为调用的是TForm2的类方法,如果用后一方法调用程序可能会产生非法访问,这是因为Form2可能未被创建。
    在TForm2.Button1Click事件中同理。