我建立了一个公用的窗体A,B继承自A,在B窗体的某一事件中动态的创建窗体C(modal);我在A窗体中声明了一个公用函数如下,其中的参数setpro和getpro为C窗体的两个赋值过程。我的初衷是让所有继承自A窗体的窗体均可以使用此函数,那样子窗体的代码量就少很多,且好维护。可现在问题是:无法将C窗体的过程传进去,如果硬将C窗体的过程(函数)传进去,就提示我‘实用过程与指针类型冲突’,无法编译。
请各位高手帮忙解决一下,错在哪儿?或者是告知是不是有其他更好的办法实现我的想法(初衷)。
谢谢!!
procedure TPublicInfoFm.SaveAll(Fm :TFormClass;Ads :TADODataSet;Setpro :TProcedure;GetPro:TProcedure);
var
PBfm : Tform;
begin
try
//根据窗体状态来判断是新增还是修改
case self.Frmstate of
1:
begin
//pbfm := fm.Create(application);
pbfm.Caption := pbfm.Caption+'(新增)';
if pbfm.ShowModal = mrok then
begin
ads.Append;
Getpro;
Ads.UpdateBatch();
end;
end;
2:
begin
//pbfm := fm.Create(application);
pbfm.Caption := pbfm.Caption+'(修改)';
if not Ads.IsEmpty then
begin
setpro;
end else
exit;
if pbfm.ShowModal = Mrok then
begin
Ads.Edit;
getpro;
Ads.UpdateBatch();
end;
end;
end; //case
pbfm.free;
pbfm := nil;
except
on E:Exception do
begin
messagebox(0,pchar(e.Message),'错误',MB_OK+MB_ICONWARNING);
end;
end;
end;
请各位高手帮忙解决一下,错在哪儿?或者是告知是不是有其他更好的办法实现我的想法(初衷)。
谢谢!!
procedure TPublicInfoFm.SaveAll(Fm :TFormClass;Ads :TADODataSet;Setpro :TProcedure;GetPro:TProcedure);
var
PBfm : Tform;
begin
try
//根据窗体状态来判断是新增还是修改
case self.Frmstate of
1:
begin
//pbfm := fm.Create(application);
pbfm.Caption := pbfm.Caption+'(新增)';
if pbfm.ShowModal = mrok then
begin
ads.Append;
Getpro;
Ads.UpdateBatch();
end;
end;
2:
begin
//pbfm := fm.Create(application);
pbfm.Caption := pbfm.Caption+'(修改)';
if not Ads.IsEmpty then
begin
setpro;
end else
exit;
if pbfm.ShowModal = Mrok then
begin
Ads.Edit;
getpro;
Ads.UpdateBatch();
end;
end;
end; //case
pbfm.free;
pbfm := nil;
except
on E:Exception do
begin
messagebox(0,pchar(e.Message),'错误',MB_OK+MB_ICONWARNING);
end;
end;
end;
解决方案 »
- FreeLibrary DLL 处理 Webbrowser 内存泄露
- 请教几个关于DELPHI7基本操作的问题
- 如何控制输出制表符?
- 急!OCX,用Delphi向导生成的OCX在PB中加不上。
- ADO+SQL SERVER在多线程环境下的使用
- 已知一个窗体的Handle,如何知道创建此窗体的程序的完整路径.
- 关于SocketConnection连接
- 为什么生成执行文件后,运行时程序退不出来?
- 总出错,请问如何用delphi 动态地添加一个worksheet给一个Excel文件
- 如何通过编程实现多个TmaskEdit控件的Onchange事件共享一个Procedure?
- 怎样使opendialog控件打开的不是选择文件对话框,而是选择目录对话框?急
- 打印的问题(Image区域)---菜鸟起步呀!
类似
class procedure TFrmSystemOptions.CallSystemOptions;
begin
if not assigned(FrmSystemOptions) then
FrmSystemOptions := TFrmSystemOptions.Create(nil);
try
FrmSystemOptions.DoSomething;
FrmSystemOptions.ShowModal;
finally
FrmSystemOptions.Free;
FrmSystemOptions:=nil;
end;
end;
class procedure SetPro(const ADataSet:TADataSet);用于显示数据,在A中从数据库得到数据后,把数据以集合形式传给C,然后C显示;
class function GetPro(): TADataSet; 用于新增数据,新增数据放在Result里返回;
再定义一个class procedure EditPro(var ADataSet:TADataSet);用于编辑数据……
:-)
好像应该这样
如果你要传窗体的过程的话
TProcedure = procedure of Object;
还有你的才c窗口的getpro,setpro如何声明的
pbfm := fm.Create(application);
这个为什么注释掉呢
TO IFindit(寻找其中的乐趣)、Canvas(霜有棱,天无情 - 天下无霜) :
我水平L,希望两位能不能再具体点。
盼!
在吗?
function ModifyData(para1, para2...): Boolean; Virtual; abstract;
在子类里声明并定义
function NewAddData(para1, para2...): Boolean; Override;
{
//新增
}
function ModifyData(para1, para2...): Boolean; Override;
{
//修改
}
挺简单的,但是如果你不明白多态的原理,可能也理解不了,赶紧找本面向对象的书,看一下多态, 等程序中第一次用到多态时,心里很爽!
Type
MyPro = procedure of object;
procedure TPublicInfoFm.SaveAll
(Fm :TFormClass;Ads :TADODataSet;Setpro :TMyPro;GetPro:TMyPro);
这样应该就可以解决了,前面 wx1452() 已经说过,不知道是不是楼主没有注意到。按照我的理解,这个函数主要就是对外隐藏了保存或者修改的区别,统一都用SaveAll,由A窗口判断来确定是否向C中写入初始值,调用Edit还是Append。不知道是否了解了楼主的意思。那么,在这一套体系中B起到了什么作用呢?为什么我不直接使用A呢?这层继承关系提供了什么方面的灵活性。这是不解一。在你的代码里两句C窗口创建的语句都被注释了,不知道是因为调试不过临时这样作的,还是根本不要这两句,如果不是在这里创建的,那么是在那里创建的呢。此外如果是已经创建好了C在调用这个方法,那么参数不应该是TFormClass。这是不解二。如果SetPro和GetPro都是C的方法,那为什么不这样调用:
pbfm.SetPro;
而要采用复杂的函数指针的方式?这是不解三。这个倒有一个可能,因为从TFormClass的实例是没办法调用到你要在C窗口中定义的方法的,那么其实你可以这样:
Type
TCFormClass = class of TCForm;
参数中传递TCFormClass类型就可以了。你是想可以统一处理各种窗口,那么这些窗口都从CForm中继承。其实整个体系需要特化的正是C窗口而不是你原来想的A窗口。我看到你传入的两个函数都是无参数的,也就是说你是通过其他方式来获取过程需要的输入和保存最终的输出,也就是DataSet中的数据。(暂时不讨论耦合的问题)。那么为什么不这么写呢。
procedure TCForm.NewRecord;
begin
FDataSet.Append;
...
FDataSet.UpdateBatch;
end;procedure TCForm.EditRecord
begin
FDataSet.Edit;
...
FDataSet.UpdateBatch;
end;
在A中直接调用C的两个函数即可,也不必传这么一大堆东西了,这是不解四。下面就是一些空泛道理了,可能一下用不上,不过我觉得你了解一些应该会比较好。
1,不要在一个函数里用一个标志变量分成不相干的两支。不知道你有没有学过高内聚低耦合的知识,如果没有或者淡忘了可以看看,这种情况是非常典型的低内聚错误。把它分成两个函数,删除那个标志变量。
2,不要用标志变量,如果一定要用把它定义为有意义的枚举类型。如
type
TFormState = (fsNew, fsModify);
FormState: TFormState
不过就算如此,还是不如干脆没有。每个标志变量都象是头朝上放在凳子上的图钉。等你放多了你就会明白它会怎么伤害你了。
3,其实你这么复杂的搞了一套,不过就是为了在每个弹出窗口中省去一句判断调用Apped还是Edit而已。值得么?如果真的这个方面重复工作这么多,应该考虑统一用一个窗口完成所有数据的新增和修改,窗口根据数据内容动态生成界面。程序构架应该表现问题的结构而不是你的实现的结构。
4,界面其实没有必要作这么多工作,应该是单纯的作显示和交互的任务即可。在界面显示的时候从后台读出需要的数据,接收了输入后调用后台对应的对象。真正体现问题解决方式的应该是业务逻辑层的对象。
TO asj() :
不解一:B是真正的显示窗体,之所以用到A是因为,除了B之外还有数个跟B一样,继承自A的窗体。
不解二:你猜测的没错,我确是在没编译过时,修改时暂注释掉,放上来忘了修正,SORRY。
不解三:asj()兄的意思是类方法?
不解四:A其实没具体实现,只不过做为父窗体存在。
其实,我也觉得可能走了弯路,但我的水平还真不知如何纠正。。
该如何??
问题解决后,我愿再开贴答谢。
你回答的什么啊?
1,我知道B是从A继承的,问题是你是出于什么考虑要让这几个窗口从A继承,我丝毫没有看出来。只是用这个函数的话就没必要了,要是每个窗口都用到stringlist难道还要都从stringlist中继承?
2,...
3,和类方法有什么关系啊?比如你生成了一个Form2,上面放了一个Edit1。你告诉我你怎么从里面读出来内容啊。
Form2.Edit1;
那如果是Form2,你在里面写了一个公有的函数Proce1,你再来告诉我怎么调用好么?
4,和A有没有具体实现有什么关系?你原来的方案没有具体实现你不是一样写了这么一大堆了,现在只是让你把那些东西都写到C里面去,A里只调用两个方法。现在有个更大的不解,你现在的问题是什么?如果是你最初提出来的那个,应该改了参数类型就OK了。如果你是想知道怎么更好的解决,我的建议是,不要搞这一套东西,除了增加你犯错的机会没什么好处。我真的不想说,不过还是得告诉你,你在基础方面差的实在是太多,像你这样的如果和我一起,恐怕我要用你写代码相等的时间来改它。不过看你的代码,如果都是你写的,那也不是完全不会编码的人写的,不知道是不是开始就是从别人的相似代码中改改拼拼中摸索过来的。如果是这样,建议你系统的学习一下Delphi编程,不要只是拉几个控件,拼个数据库程序就算完工了。否则很多东西你的假定和基本的思路都是错的自己还没有意识,这种问题别人很难一句一句给你很快讲明白的。建议你看看《Delphi5开发人员指南》