主程序界面的菜单中有一个菜单项目负责调用一个窗口CustomerKindForm;当这个窗口OnCreate的时候调用一个方法,如下:
procedure TCreditLevelForm.FormCreate(Sender: TObject);
begin
Self.InitInterface ;
end;InitInterface方法代码如下:
procedure TCreditLevelForm.InitInterface;
begin
ComboBox1.ItemIndex:=0;
Edit2.Text :=InfoManager.GetMaxCode('Dict_CreditConfig');
with DBGrid1,Self.Frame21.ADOQuery1 do
begin
Columns[0].FieldName := 'XinYuLX';
Columns[1].FieldName := 'XinYuBM';
Columns[2].FieldName := 'XinYuMC';
Columns[3].FieldName := 'QiShiZhi';
Columns[4].FieldName := 'ZhongZhiZhi';
Columns[5].FieldName := 'ZhuXiaoBS';
InfoManager.ShowCreditLevelData ; //当执行到这里的时候调用类TInfoManager的方法来在DBGrid中显示相关数据
//类TInfoManager在单元ModuleFrame中定义,并且在此单元定义全局变量InfoManager
end;
Self.SetFocusedControl(Edit4);
end;ShowCreditLevelData方法代码如下:
procedure TInfoManager.ShowCreditLevelData;
begin
with CreditLevelForm.Frame21.ADOQuery1 do //执行到这里马上报一个内存访问错误,为什么?
begin
Close;
SQL.Text:='Select *,'+
'XinYuLX=Case XinYuLB '+
'When 0 Then ''供应商'' '+
'When 1 Then ''承运商'' '+
'Else ''客户'' End,'+
'ZhuXiaoBS=case ZhuXiaoBZ '+
'When 1 Then ''√'' '+
'When 0 Then ''''End '+
'From Dict_CreditConfig';
Open;
end;
end;
procedure TCreditLevelForm.FormCreate(Sender: TObject);
begin
Self.InitInterface ;
end;InitInterface方法代码如下:
procedure TCreditLevelForm.InitInterface;
begin
ComboBox1.ItemIndex:=0;
Edit2.Text :=InfoManager.GetMaxCode('Dict_CreditConfig');
with DBGrid1,Self.Frame21.ADOQuery1 do
begin
Columns[0].FieldName := 'XinYuLX';
Columns[1].FieldName := 'XinYuBM';
Columns[2].FieldName := 'XinYuMC';
Columns[3].FieldName := 'QiShiZhi';
Columns[4].FieldName := 'ZhongZhiZhi';
Columns[5].FieldName := 'ZhuXiaoBS';
InfoManager.ShowCreditLevelData ; //当执行到这里的时候调用类TInfoManager的方法来在DBGrid中显示相关数据
//类TInfoManager在单元ModuleFrame中定义,并且在此单元定义全局变量InfoManager
end;
Self.SetFocusedControl(Edit4);
end;ShowCreditLevelData方法代码如下:
procedure TInfoManager.ShowCreditLevelData;
begin
with CreditLevelForm.Frame21.ADOQuery1 do //执行到这里马上报一个内存访问错误,为什么?
begin
Close;
SQL.Text:='Select *,'+
'XinYuLX=Case XinYuLB '+
'When 0 Then ''供应商'' '+
'When 1 Then ''承运商'' '+
'Else ''客户'' End,'+
'ZhuXiaoBS=case ZhuXiaoBZ '+
'When 1 Then ''√'' '+
'When 0 Then ''''End '+
'From Dict_CreditConfig';
Open;
end;
end;
with ADOQuery1 do
begin
Close;
SQL.Text:='Select *,'+
'XinYuLX=Case XinYuLB '+
'When 0 Then ''供应商'' '+
'When 1 Then ''承运商'' '+
'Else ''客户'' End,'+
'ZhuXiaoBS=case ZhuXiaoBZ '+
'When 1 Then ''√'' '+
'When 0 Then ''''End '+
'From Dict_CreditConfig';
Open;
end;
然后在ShowCreditLevelData中调用这个方法试试
CreditLevelForm.Frame21是frame的实例
然后我在另外一个单元中定义类TInfoManager,最后给其设计一个方法访问CreditLevelForm上的对象Frame21,就这么一个过程!但在这个方法ShowCreditLevelData中老是报内存访问错误!
这个应该是在Tframe2里定义的吧?procedure TInfoManager.ShowCreditLevelData;
begin
with CreditLevelForm.Frame21.ADOQuery1 do
你这样就好比是这样TA=Class
procedure aa;
end;TB=class
a:Ta;
procedure bb;
end;var b:Tb;procedure Ta.aa;
b.bb;
end;
你觉得这段代码有什么问题?
procedure TCustomerKindForm.FormCreate(Sender: TObject);
begin
Self.InitInterface ;
end;接着,进入InitInterface过程,如下:
procedure TCustomerKindForm.InitInterface;
begin
ComboBox1.ItemIndex:=0;
Edit2.Text := InfoManager.GetMaxCode('Dict_CustomerKind');
with DBGrid1,CustomerKindForm.Frame21.ADOQuery1 do
begin
Columns[0].FieldName :='KeHuLX';
Columns[1].FieldName :='LeiBieBM';
Columns[2].FieldName :='LeiBieMC';
Columns[3].FieldName :='ZhuXiaoBS';
if Assigned(Self.Frame21.ADOQuery1 ) then //到这里可以显示一个对话框
ShowMessage('Exists');
InfoManager.ShowCustomerData ; //从这里进入ShowCustomerData方法
end;
Self.SetFocusedControl(Edit2);
end;最后进入ShowCustomerData方法,如下:
procedure TInfoManager.ShowCustomerData;
begin
if Assigned(CustomerKindForm.Frame21.ADOQuery1 ) then //这里报内存访问错误!
ShowMessage('Exists');
with CustomerKindForm.Frame21.ADOQuery1 do
begin
Close;
SQL.Text:='Select *,'+
'KeHuLX=Case KeHuLB '+
'When 0 Then ''供应商'' '+
'When 1 Then ''承运商'' '+
'Else ''客户'' End,'+
'ZhuXiaoBS=case ZhuXiaoBZ '+
'When 1 Then ''√'' '+
'When 0 Then ''''End '+
'From Dict_CustomerKind';
Open;
end;
end;------------------------------------------------------------
各位帮忙看看为什么?脑袋都大了!
informanager创建了没有????
InfoManager.ShowCustomerData ;
procedure TInfoManager.ShowCustomerData;
begin
if Assigned(CustomerKindForm.Frame21.ADOQuery1 ) then //这里报内存访问错误!
ShowMessage('Exists');
////////////////Frame21是在那里定义的?------》我New----Frame定义了一个TFrame2类,然后我在CreditLevelForm中进行引用,这样在
TCreditLevelForm的类申明中就有了这样的部分:Frame21: TFrame2;//////////
然后我在另外一个单元中定义类TInfoManager,最后给其设计一个方法访问CreditLevelForm上
的对象Frame21,
///////////////
TInfoManager里没有Frame21的实例阿 你这样调用它的方法不出错才怪
procedure TMainForm.Action18Execute(Sender: TObject);
begin
gError:=SetCreditLevel; //SetCreditLevel是CreditLevelForm的一个独立的函数
if gError<>'' then
begin
Application.MessageBox(PChar(gError),'错误',MB_ICONERROR+MB_OK);
Exit;
end;
end;
其中SetCreditLevel代码如下
function SetCreditLevel:String;
var
vErrStr:String;
begin
vErrStr:='';
if not CommonFunc.IsExistForm('CreditLevelForm') then
try
CreditLevelForm:=TCreditLevelForm.Create(Application);
except
vErrStr:='调用车辆信誉等级窗口错误.';
Result:=vErrStr;
Exit;
end;
end;
其中再次调用CommonFunc单元的独立方法IsExistForm来判断名为'CreditLevelForm'的窗体是否当前存在,如果返回False,说明不存在,动态创建。IsExistForm函数代码如下
function IsExistForm(AFormName:String):Boolean;
var
I:Integer;
begin
Result:=False;
for I:=0 to Screen.FormCount-1 do
if Screen.Forms[I].Name=AFormName then
begin
Result:=True;
Break;
end
end;到这里开始触发CreditLevelForm的OnCreate事件,如下
procedure TCreditLevelForm.FormCreate(Sender: TObject);
begin
Self.InitInterface ;
end;接着进如初始化界面的过程,如下
procedure TCreditLevelForm.InitInterface;
begin
ComboBox1.ItemIndex:=0;
Edit2.Text :=InfoManager.GetMaxCode('Dict_CreditConfig');
with DBGrid1,Self.Frame21.ADOQuery1 do
begin
Columns[0].FieldName := 'XinYuLX';
Columns[1].FieldName := 'XinYuBM';
Columns[2].FieldName := 'XinYuMC';
Columns[3].FieldName := 'QiShiZhi';
Columns[4].FieldName := 'ZhongZhiZhi';
Columns[5].FieldName := 'ZhuXiaoBS';
//行位置一
InfoManager.ShowCreditLevelData ; //这里跳转
end;
Self.SetFocusedControl(Edit4);
end;初始化的后期跳转到在另外一个单元定义的一个类TInfoManager的方法ShowCreditLevelData的代码上,如下
procedure TInfoManager.ShowCreditLevelData;
begin
//行位置二
with CreditLevelForm.Frame21.ADOQuery1 do //然后在这里出错!为什么?
begin
Close;
SQL.Text:='Select *,'+
'XinYuLX=Case XinYuLB '+
'When 0 Then ''供应商'' '+
'When 1 Then ''承运商'' '+
'Else ''客户'' End,'+
'ZhuXiaoBS=case ZhuXiaoBZ '+
'When 1 Then ''√'' '+
'When 0 Then ''''End '+
'From Dict_CreditConfig';
Open;
end;
end;-----------------------------------------------------------
如果我在上述代码的行位置一和二处分别加语句
if Assigned(CreditLevelForm.Frame21.ADOQuery1) then
ShowMessage('Exist');
然后单步调试,在位置一上可以显示,但到了位置二马上就报一个内存访问错误,很是蹊跷!
begin
ComboBox1.ItemIndex:=0;
Edit2.Text := InfoManager.GetMaxCode('Dict_CustomerKind');
with DBGrid1,CustomerKindForm.Frame21.ADOQuery1 do
begin
Columns[0].FieldName :='KeHuLX';
Columns[1].FieldName :='LeiBieBM';
Columns[2].FieldName :='LeiBieMC';
Columns[3].FieldName :='ZhuXiaoBS';
if Assigned(Self.Frame21.ADOQuery1 ) then //到这里可以显示一个对话框
ShowMessage('Exists');
InfoManager.ShowCustomerData ; ---》这里调用InfoManager类方法
///////////
TCustomerKindForm是从这里进入的InfoManager
begin
if Assigned(aForm.Frame21.ADOQuery1 ) then // 这样总该可以了吧
ShowMessage('Exists');
....
....
begin
ComboBox1.ItemIndex:=0;
Edit2.Text :=InfoManager.GetMaxCode('Dict_CreditConfig');
with DBGrid1,Self.Frame21.ADOQuery1 do
//////
在这里没有错 因为Frame21是属于TCreditLevelForm的方法这样像阿德说的 ta=class
方法a你想在tb=class里
ta.方法a
这是不行的要么 tb里
xx=ta.Create
xx.方法a在一个类中对其他的类的控制权只有 通过实例来控制
如果想达到你要的效果 xx=ta.Create
xx.方法a 这样也不行他是同态建立所以你可以在TCustomerKindForm里写一个方法返回
Assigned(Self.Frame21.ADOQuery1 )
(2003-09-05 16:10:42) FrameSniper
现在是三个单元申明三个东西
ModuleDM----TFrame2
CreditLevelFrm----TCreditLevelForm
ModuleFrame----TInfoManager
begin
ComboBox1.ItemIndex:=0;
Edit2.Text := InfoManager.GetMaxCode('Dict_CustomerKind');
with DBGrid1,CustomerKindForm.Frame21.ADOQuery1 do
begin
Columns[0].FieldName :='KeHuLX';
Columns[1].FieldName :='LeiBieBM';
Columns[2].FieldName :='LeiBieMC';
Columns[3].FieldName :='ZhuXiaoBS';
if Assigned(Self.Frame21.ADOQuery1 ) then
//////////
在这里没错
因为Frame21是TCustomerKindForm的方法 可以Self.Frame21.ADOQuery1 这样来用
但是在TInfoManager中
procedure TInfoManager.ShowCreditLevelData;
begin
//行位置二
with CreditLevelForm.Frame21.ADOQuery1 do 这样用就是阿德说的 ta=class
方法a
你想在tb中 tb=class
ta.方法a
这样是不行的 在一个类中对其他类的控制权只能通过实例 比方 tb=class
xx=ta.Create
xx.方法a这样动态建立又不能达到你的效果
所以你最好在TCustomerKindForm中建一个方法返回CustomerKindForm.Frame21.ADOQuery1的值
begin
//行位置二
with aForm.Frame21.ADOQuery1 do //然后在这里出错!为什么?因为构造函数已经执行,Self已经存在,所以应该就可以了。
Self.SetFocusedControl(Edit4);
好象也不对
但如果我在CreditLevelForm的OnCreate的第一句换成
ShowMessage(Self.Caption);这里也可以显示成功,和你们说的想矛盾,因为如果CreateLevelForm没有意义,就说明栈上的对象不存在,因为TCreditLevelForm.Create没有执行完成。这样肯定取不到Caption这个值了,因为这个值是存放在栈中的!但实际是在执行OnCreate的代码前是可以取到的,这就说明在触发这个事件的代码前所有的对象都是创建了的!所以在执行到我出错的地方的时候CreditLevelForm这个对象指针是早已有意义的! 况且,可以看到在InitInterface方法的开始我就访问了CreditLevelForm上的ComboBox1和Edit2,如果说CreditLevelForm这个指针没有意义,那么是根本访问不了这两个控件的! 所以,个人感觉答案尚不明确!期待中.........
ShowMessage(Self.Name);这样的句子,这里访问的是私有数据,而私有数据是存放在栈上的对象实体空间中的,如果说在触发OnCreate事件前对象不存在,那么是根本无法访问这些私有数据的。因此,在触发前对象是已经创建的!
方法a ----------------------------->Frame21.ADOQuery1tb=class----------------------------->TInfoManager
ta.方法a------------------------------>CustomerKindForm.Frame21.ADOQuery1
感觉出不对来了吧 一个类调用另一个类 1我说的实例 2猛禽的传控制权
procedure TInfoManager.ShowCreditLevelData;
var
xx:TCreditLevelForm
begin
//行位置二 xx:=TCreditLevelForm.creat
with xx.Frame21.ADOQuery1 do 这样就是通过实例引用了
猛禽的传值不失一个好方法 但现在麻烦就是在creat传递self 我个人同意你的观点
在栈里很多东西都没有初始化如果不是在 creat里 那我想应该没问题
unit CreditLevelFrm
....
TCreditLevelForm=class(TForm)
....
Frame21:TFrame2;
procedure InitInterface;
procedure FormCreate(Sender: TObject);
....
end;
....
procedure TCreditLevelForm.InitInterface;
begin
....
InfoManager.ShowCreditLevelData ;
....
end;
procedure TCreditLevelForm.FormCreate(Sender:TObject);
begin
Self.InitInterface ;
end;2.单元ModuleFrame.pas里面:
unit ModuleFrame
....
TInfoManager=class
....
procedure InitInterface;
....
end;
....
procedure TInfoManager.ShowCreditLevelData;
begin
with CreditLevelForm.Frame21.ADOQuery1 do //a AV fault here!
....
end;3.单元ModuleDM.pas里面:
unit ModuleDM;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, ADODB, SysDM;type
TFrame2 = class(TFrame)
ADOQuery1: TADOQuery;
DataSource1: TDataSource;
private
{ Private declarations }
public
{ Public declarations }
end;implementation{$R *.dfm}end.
以上就是我的单元结构,小伍!和你说的不一样哦!
你的理解还是不对,再把偶们几个的跟贴仔细看看吧。^_^
begin
with CreditLevelForm.Frame21.ADOQuery1 do //执行到这里马上报一个内存访问错误,
//..
end;CreditLevelForm 创建了吗?报内存访问错误,多半是访问了一个不存在的对象或者指针,
To myling(阿德):
//类TInfoManager在单元ModuleFrame中定义
//CreditLevelForm.Frame21.ADOQuery1
//你在类中访问实例,当然出错了!!!在类中访问类实例会报错吗 ?
我经常在一个类中访问这个类的一个实例,不会报错啊,
TA=Class
procedure aa;
end;TB=class
a:Ta;
procedure bb;
end;var b:Tb;
procedure Ta.aa;
b.bb;
end;
我认为出错的地方有:
1,a:Ta在tb类的create中没有创建;
2,b:Tb定义为全局变量,而且ta操纵的是固定了的b:Tb这一个全局变量;
你的程序中b是数据模块或者窗体,是否这些数据模块或者窗体已经创建了?(一定要是application.CrateForm()这样的创建形势,即b作为全局变量创建,不能是在汉书或者过程中的局部变量)
3, 同意huojiehai(海天子) ,将代码最好移到OnShow中试试
不同意hkbarton(宁静至远||淡泊明志) 的,不必通过post一个消息来解决
4,Frame与本问题关系并不大,如果该单元中并没有于特定变量相关的代码,即使有,如果这些变量是真正的全局变量,也无所谓。
begin
with CreditLevelForm.Frame21.ADOQuery1 do //执行到这里马上报一个内存访问错误,
...
end对了,这样写是很容易报错的,在一个类里面直接引用另外一个类的实例,
要是把 CreditLevelForm 通过参数传递进来,
在访问 CreditLevelForm前先判断一下是不是创建了这个类的实例,
这样可能会安全些。
with CreditLevelForm.Frame21.ADOQuery1 do 这三个变量中总有一个是没有创建的.
如何Post,可以说的详细点吗?To 云意 还没有,乱套了,脑子都乱了,明天调试吧!脑子糊涂了!
if not Assigned(CreditLevelForm) then ShowMessage('Exist');结果这里居然出现,乱套了!
我认为比如说()
var
WM_ShowCreditLevelData=WM_USER+1000;
procedure TCreditLevelForm.FormCreate(Sender: TObject);
begin
postmessage(handle,WM_ShowCreditLevelData,0,0);//
end;
然后在定义一个处理这个消息的过程
procedure WMShowCreditLevelData(var msg:Tmessage);//messageWM_ShowCreditLevelData
begin
Self.InitInterface ;
end;
今天早上好很兴奋的告诉我,找到原因了因为 Frame21没创建我回的帖子反复强调 你要创建实例 要不就像猛禽传递指针这家伙到地仔细看帖子了没有 靠 大家不要回了
begin
ComboBox1.ItemIndex:=0; //1
Edit2.Text := InfoManager.GetMaxCode('Dict_CustomerKind'); //2
with DBGrid1,CreditLevelForm.Frame21.ADOQuery1 do //3
begin
Columns[0].FieldName :='KeHuLX';
Columns[1].FieldName :='LeiBieBM';
Columns[2].FieldName :='LeiBieMC';
Columns[3].FieldName :='ZhuXiaoBS';
InfoManager.ShowCustomerData ;
end;
Self.SetFocusedControl(Edit2);
end;上面代码是InitInterface的代码,行1、2和3处,如果我按F4到行1上停止,这个时候我把鼠标分别放到行1的ComboBox1上看到RTTI给返回内容,可以访问;接着我把鼠标放到行2的Edit2上看到RTTI继续给返回内容,表示也可以访问;接着,我把鼠标放到行3的CreditLevelForm上,RTTI也给返回表示可以访问,但是个空值(这个很正常,全局的非简单类型变量要进行初始化的,所以这里为空Nil);但最后当我把鼠标放到Frame21上的时候,却提示是无法访问的,也就说明这个对象根本还没有建立!这里就有个奇怪的问题,为什么ComboBox1、Edit2和Frame21都是CreditLevelForm上的控件,但到了这个地方前两个可以访问,后一个却无法访问,而且都是在CreditLevelForm为Nil的情况下?谁来给我解释解释为什么?另外一个问题就是更正我以前的一个看法:在触发OnCreate事件的时候所有的对象是没有创建的!在OnCreate里面访问Self不会出错,但访问自身变量名称马上出错!谁来解释一下什么时候开始访问二者就等价了?
AD,HKBarton,DuXin,Raptor,LeapMars每个赠送200分!谢谢各位积极参与,让俺认识到自己犯的一个概念错误,呵呵.........