从另一个表单访问 DBGrid1.Columns[1].Title.Caption
Access DBGrid1.Columns[1].Title.Caption from another Form
我正在尝试从另一个表单访问 dbgrid.field 的 Caption
。
我这里用的是MDI,两种形式都是MDIChildren。
我试图从另一个表单执行以下 ShowMessage
但它导致了访问冲突:
ShowMessage(Form1.DBGrid1.Columns[1].Title.Caption); // 1st try
ShowMessage(Unit1.Form1.DBGrid1.Columns[1].Title.Caption); // 2nd try
已在 2 种形式之间使用集合。
错误信息是
Access Violation at address 000010363F9 in module. Read of address 000000006F0.
我在这里错过了什么?
更新:这是本案例的精确复制 (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.
错误信息
Access Violation at address 0081B314 in module 'Project7.exe'. Read of
address 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 实例是自动创建的 ChildForm1
.
使用自动创建的表单,也许主表单除外,通常被认为是不好的做法,因为它会助长此类事故,因此最好改掉使用它们的习惯。
从一个表单(或数据模块)访问另一个表单(或数据模块)的一种不太容易发生事故的技术是以一种需要您指定要操作的对象实例的方式在 "other" 表单上编写代码。像这样:
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 实例
意思是,因为当您有多个相同的实例时,正确处理可能非常重要
表单(即使您不这样做,因为它可能会提示您怀疑实例是否已创建)。
我正在尝试从另一个表单访问 dbgrid.field 的 Caption
。
我这里用的是MDI,两种形式都是MDIChildren。
我试图从另一个表单执行以下 ShowMessage
但它导致了访问冲突:
ShowMessage(Form1.DBGrid1.Columns[1].Title.Caption); // 1st try
ShowMessage(Unit1.Form1.DBGrid1.Columns[1].Title.Caption); // 2nd try
已在 2 种形式之间使用集合。
错误信息是
Access Violation at address 000010363F9 in module. Read of address 000000006F0.
我在这里错过了什么?
更新:这是本案例的精确复制 (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.
错误信息
Access Violation at address 0081B314 in module 'Project7.exe'. Read of address 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 实例是自动创建的 ChildForm1
.
使用自动创建的表单,也许主表单除外,通常被认为是不好的做法,因为它会助长此类事故,因此最好改掉使用它们的习惯。
从一个表单(或数据模块)访问另一个表单(或数据模块)的一种不太容易发生事故的技术是以一种需要您指定要操作的对象实例的方式在 "other" 表单上编写代码。像这样:
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 实例 意思是,因为当您有多个相同的实例时,正确处理可能非常重要 表单(即使您不这样做,因为它可能会提示您怀疑实例是否已创建)。