关于自定义事件(100分)

  • 主题发起人 主题发起人 vickymade
  • 开始时间 开始时间
V

vickymade

Unregistered / Unconfirmed
GUEST, unregistred user!
假如我想给我的主窗体frmMain定义一个打开子窗体frmClient的事件OnOpenClient,我应该怎么做啊?再现等待ing。期盼各位高手相助。
 
跟其它空间的定义方法一样!
在public中定义:
property OnOpenClient Read FOnOpenClient write FOnOpenClient;

在你现有调用事件的位置 写代码
if aggigned(FOnOpenClient) then OnOpenClient(self);
 
不回大的哥们儿麻烦顶一下`
 
定义一个公用过程来调用不行吗?
 
但是我的主窗体可能拥有很多个子窗体,我想在触发这个事件的时候去选择到底打开那个子窗体,这个时候,就应该加入子窗题的类型T***ClientForm,然后才能正确的打开丫。

举个例子,我想打开AAAClientForm,打开这个窗体以前呢,我想判断一下,这个窗体是否已经打开了。如果已经打开了,我就不做任何操作,如果没有打开,我就打开它。这个时候我应该怎么做?
 
if assign() then
這種樣子。
 
现在我的解决方法就是将事件写在TClientForm里面,但是不能写在TMainForm里吗?最关键的问题就是怎样定义和响应能够输入多个参数的事件,以及该事件的处理过程。
 
if assign() then

要么定义一个全局变量来保存这些已经打开的form标识,然后从这个变量中判断
 
事件,事件,我想用事件来处理
 
还有,我为什么这样做[代码付后]执行到触发事件的时候为什么报错呢?说什么读写内存错误,而且内存地址都是0000000什么的。



type
TClientBaseForm = class(TForm)
ToolBar: TToolBar;
procedure FormDestroy(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
//Events
FOpened,FClosed : TNotifyEvent;
FOpenChildren: TNotifyevent;
FCloseChildren: TNotifyevent;
//Procedures
Procedure Opened(Sender : TObject ; AForm : TClientBaseForm);
Procedure Closed(Sender : TObject ; AForm : TClientBaseForm);
public
{ Public declarations }
property OnOpened:TNotifyevent read FOpenChildren write FOpenChildren;
property OnClosed:TNotifyevent read FCloseChildren write FCloseChildren;

end;

var
ClientBaseForm: TClientBaseForm;

implementation

{$R *.dfm}

procedure TClientBaseForm.Closed(Sender: TObject; AForm: TClientBaseForm);
begin
MainForm.ToolBar.Visible:=False;
ToolBar.Parent:=MainForm.CoolBar;
end;

procedure TClientBaseForm.Opened(Sender: TObject; AForm: TClientBaseForm);
begin
ToolBar.Parent:=Self;
MainForm.ToolBar.Visible:=True;
end;


procedure TClientBaseForm.FormDestroy(Sender: TObject);
begin
Self:=Nil;
end;

procedure TClientBaseForm.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
OnClosed(Self);
Action:=CaFree;
end;

procedure TClientBaseForm.FormShow(Sender: TObject);
begin
OnOpened(Self)
end;
 
这样:
type
TFormA = class(TForm)
public
procedure openclient(AForm : TClientBaseForm);
end;

procedure FormA.openclient(AForm : TClientBaseForm);
begin
//需要包含单元:Dbrf,可以看看帮助,你要的就是这个
if not isnullid(AForm) then
FreeAndNil(AForm);
AForm := TClientBaseForm.create(Application);
end;
 
以下是MDI软件中典型的做法,反正我是这么实现的:
procedure TMainForm.ChwiseMainExecute(Sender: TObject);
begin
case (Sender as TComponent).Tag of
1:begin
if FormXcmzin=nil then Application.CreateForm(TFormXcmzin, FormXcmzin);
FormXcmzin.BringToFront;
end;
2:begin
if FormCustomerin=nil then Application.CreateForm(TFormCustomerin, FormCustomerin);
FormCustomerin.BringToFront;
end;
3:begin
if FormProject1in=nil then Application.CreateForm(TFormProject1in, FormProject1in);
FormProject1in.BringToFront;
end;
4:begin
if FormProduct1in=nil then Application.CreateForm(TFormProduct1in, FormProduct1in);
FormProduct1in.BringToFront;
end;
5:begin
if FormWindowDef1in=nil then Application.CreateForm(TFormWindowDef1in, FormWindowDef1in);
FormWindowDef1in.BringToFront;
end;

else
MessageBox(MainForm.Handle,'对不起, 还没有提供该操作!','提示',MB_OK or MB_ICONINFORMATION);
end;
end;
 
晕S,这些常规的办法偶都能写出来,问题是偶现在想要用事件来完成。纯粹的面向对象的编程,把所有的东东都写到事件里面,呵呵,这不是商业程序,只是自己用来练得。
 
还有,我为什么这样做[代码付后]执行到触发事件的时候为什么报错呢?说什么读写内存错误,而且内存地址都是0000000什么的[red]。
//这个估计是你没有给你的事件赋值,但是却要执行这个事件指向的函数。[/red]


type
TClientBaseForm = class(TForm)
ToolBar: TToolBar;
procedure FormDestroy(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
//Events
FOpened,FClosed : TNotifyEvent;
FOpenChildren: TNotifyevent;
FCloseChildren: TNotifyevent;
//Procedures
Procedure Opened(Sender : TObject ; AForm : TClientBaseForm);
Procedure Closed(Sender : TObject ; AForm : TClientBaseForm);
public
{ Public declarations }
property OnOpened:TNotifyevent read FOpenChildren write FOpenChildren;
property OnClosed:TNotifyevent read FCloseChildren write FCloseChildren;

end;

var
ClientBaseForm: TClientBaseForm;

implementation

{$R *.dfm}

procedure TClientBaseForm.Closed(Sender: TObject; AForm: TClientBaseForm);
begin
MainForm.ToolBar.Visible:=False;
ToolBar.Parent:=MainForm.CoolBar;
end;

procedure TClientBaseForm.Opened(Sender: TObject; AForm: TClientBaseForm);
begin
ToolBar.Parent:=Self;
MainForm.ToolBar.Visible:=True;
end;


procedure TClientBaseForm.FormDestroy(Sender: TObject);
begin
Self:=Nil;//估计这一句话没有用
end;

procedure TClientBaseForm.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
OnClosed(Self);//加 assign 判断
Action:=CaFree;
end;

procedure TClientBaseForm.FormShow(Sender: TObject);
begin
OnOpened(Self)//加 assign 判断
end;


 
晕S,跟楼上说的没有关系,我发出来的是“简写”,assign 什么的都判断了,但是只要响应事件,就报错,只要是不响应就不饱错,问题应该在于我得响应函数,有两个输入参数。
 
这个问题已经讨论了好多次了,
问题是你怎样得到窗体的类名?
有几种方法:
1。存在文件中,2。存在数据库中,3。根据菜单一个一个判断(太麻烦了,不建议使用)
一个例子;
var
FrmClass: TFormClass;
FrmClassName: string;
DynForm:TForm;
begin
if Node.Count = 0 then //Select A Module
begin
QueryFormClass.Locate('Module_ID', PLData(LItem.Data)^.MODULE_ID, []);//存在数据库中
FrmClassName := Trim(QueryFormClass.FieldByName('Formclass').Text);
for i := 0 to (Owner as TForm).MDIChildCount - 1 do
if Uppercase((Owner as TForm).MDIChildren.ClassName) = Uppercase(FrmClassName) then
begin
//如果存在就直接显示,放到最前面来
(Owner as TForm).MDIChildren.Show;
if (Owner as TForm).MDIChildren.WindowState = wsMinimized then
(Owner as TForm).MDIChildren.WindowState := wsNormal;
System.Exit;
end;

//不存在就根据类名创建一个。
try
FrmClass := TFormClass(FindClass(FrmClassName));
DynForm := TForm(FrmClass.Create(Owner));
DynForm.Caption := NewFormCaption;
DynForm.Show;
except
end;
end;
 
TO 楼主:
您可能没注意到我那个过程,ChwiseMainExecute,它是一个ActionExecute,换句
话说,您现在要转换成OOP,由于这里不涉及到数据,那其实就是如何控制该ActionExecute,
那好办,您可以在经典处理的基础上,加上自定义消息,并通过消息的发送与接受来处理
不就可以了。
 


问题在于不能增加参数,这个问题不解决,不结帖子
 
这个 TClientBaseForm = class(TForm)
写的有问题。首先假设你已经在实现部分对FOnChildrenOp事件做了读写操作。那么
你的 你在什么地方执行了 FOnCHildren这个事件?
Procedure Opened(Sender : TObject ; AForm : TClientBaseForm);
Procedure Closed(Sender : TObject ; AForm : TClientBaseForm);
都是Private的。公开的OnOpened,OnClosed中也不见对
FOpenChildren: TNotifyevent;
FCloseChildren: TNotifyevent;
这两个事件的执行。
//由于代码不全,难于说清问题的所在,建议贴全代码和 详细查看。上面提到的两个时间是否被执行了以及,他们在类实现中是否被正确的读写多。而不是空的。
 
property OnOpened;
property OnClosed
没有看到被外界访问。为什么要PUBLIC????????????
 
后退
顶部