从其他窗体访问DBGrid1.Columns[1].Title.Caption



我正试图从另一个表单访问dbgrid.field的Caption

我在这里使用MDI,两种形式都是MDI儿童。

我试图从另一个表单执行以下ShowMessage,但它导致了访问冲突:

ShowMessage(Form1.DBGrid1.Columns[1].Title.Caption); // 1st try
ShowMessage(Unit1.Form1.DBGrid1.Columns[1].Title.Caption); // 2nd try

已在两个表单之间使用集合。

错误消息为

模块中地址000010363F9处的访问冲突。读取地址000000006F0。

这里缺少什么?


UPDATE:这是这个案例的精确复制(RME(。

MDI父

unit MainUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus;
type
TParentForm = class(TForm)
mmMenu: TMainMenu;
miForm1: TMenuItem;
miForm2: TMenuItem;
procedure miForm1Click(Sender: TObject);
procedure miForm2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
ParentForm: TParentForm;
implementation
uses
Form1Unit, Form2Unit;
{$R *.dfm}
procedure TParentForm.miForm1Click(Sender: TObject);
begin
TChildForm1.Create(self).Show;
end;
procedure TParentForm.miForm2Click(Sender: TObject);
begin
TChildForm2.Create(self).Show;
end;
end.

MDI ChildForm1

unit Form1Unit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Datasnap.DBClient,
Datasnap.Provider, MemDS, DBAccess, Uni, UniProvider, MySQLUniProvider,
Vcl.Grids, Vcl.DBGrids;
type
TChildForm1 = class(TForm)
dbgrd1: TDBGrid;
ucn1: TUniConnection;
mup1: TMySQLUniProvider;
uq1: TUniQuery;
dsp1: TDataSetProvider;
cds1: TClientDataSet;
ds1: TDataSource;
smlntfldcds1actor_id: TSmallintField;
strngfldcds1first_name: TStringField;
strngfldcds1last_name: TStringField;
dtmfldcds1last_update: TDateTimeField;
private
{ Private declarations }
public
{ Public declarations }
end;
var
ChildForm1: TChildForm1;
implementation
uses
MainUnit, Form2Unit;
{$R *.dfm}
end.

MDI ChildForm2

unit Form2Unit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TChildForm2 = class(TForm)
btn1: TButton;
procedure btn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
ChildForm2: TChildForm2;
implementation
uses
MainUnit, Form1Unit;
{$R *.dfm}
procedure TChildForm2.btn1Click(Sender: TObject);
begin
ShowMessage(Form1Unit.ChildForm1.dbgrd1.Columns[2].Title.Caption);
end;
end.

错误消息

模块"Project7.exe"中地址0081B314处的访问冲突。第页,共页地址000003D0。

可能其中一个对象没有分配,我怀疑它可能是Columns[1](注意Columns集合是基于零的索引,所以第一列是Columns[0](

试试这个:

if(not Assigned(Form1)) then 
raise Exception.Create('Form1 not assigned');
if(not Assigned(Form1.DBGrid1)) then 
raise Exception.Create('Form1.DBGrid1 not assigned');
if(Form1.DBGrid1.Columns.Count < 2) then 
raise Exception.Create('Form1.DBGrid1 has not the Columns[1] item');

编写像Form1Unit.ChildForm1.dbgrd1.Columns[2].Title.Caption)这样的代码会造成等待发生的事故,因为它假设您要操作的ChildForm1的实例是自动创建的CCD_ 7。

使用自动创建的表单,除了主表单之外,通常被认为是一种糟糕的做法,因为它会引发这样的事故,所以最好改掉使用它们的习惯。

从另一个窗体(或数据模块(访问一个窗体时,一种不太容易发生意外的技术是在"另一个"窗体上以需要指定要操作的对象实例的方式编写代码

procedure TChildForm2.DoSomethingWithForm1(Form1Instance : TForm1);
begin
ShowMessage(Form1Instance.dbgrd1.Columns[2].Title.Caption);
end;
procedure TChildForm2.btn1Click(Sender: TObject);
begin
DoSomethingWithForm1(Form1Unit.ChildForm1);
end;

这样做的意义在于,它迫使你思考你的Form1实例意思是说,因为当你有多个相同的实例时,正确处理可能非常重要表单(即使没有,因为它可能会提示您怀疑实例是否已创建(。

最新更新