我想在应用程序启动后使用自己定制的Hint,那么我先试着把这样写代码:
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
...
private
...
public
procedure DrawHint(Sender:TObject);
end;
var
...
implementation
{$R *.dfm}procedure TForm1.DrawHint(Sender:TObject);
begin
...
end;
procedure TForm1.FormCreate(Sender:TObject);
begin
application.onhint:=DrawHint;
end;结果运行是正常的,达到了我预期的效果,那么我又把代码改成下面的样子:
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
...
private
...
public
end;
var
...
procedure DrawHint; //注意,声明放在了单元的全局变量部分
implementation
{$R *.dfm}procedure DrawHint;
begin
...
end;
procedure TForm1.FormCreate(Sender:TObject);
begin
application.onhint:=DrawHint;
end;这样程序就无法编译通过了,为什么呢?包括我在运行时动态生成的菜单项等等的事件都必须在主窗体的成员部分声明才可以关联执行?
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
...
private
...
public
procedure DrawHint(Sender:TObject);
end;
var
...
implementation
{$R *.dfm}procedure TForm1.DrawHint(Sender:TObject);
begin
...
end;
procedure TForm1.FormCreate(Sender:TObject);
begin
application.onhint:=DrawHint;
end;结果运行是正常的,达到了我预期的效果,那么我又把代码改成下面的样子:
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
...
private
...
public
end;
var
...
procedure DrawHint; //注意,声明放在了单元的全局变量部分
implementation
{$R *.dfm}procedure DrawHint;
begin
...
end;
procedure TForm1.FormCreate(Sender:TObject);
begin
application.onhint:=DrawHint;
end;这样程序就无法编译通过了,为什么呢?包括我在运行时动态生成的菜单项等等的事件都必须在主窗体的成员部分声明才可以关联执行?
以为Application.OnHint是一个方法指针
property OnHint: TNotifyEvent read FOnHint write FOnHint;
TNotifyEvent = procedure(Sender: TObject) of object;
而你的第二种方法是一个过程
type TNotifyEvent = procedure (Sender: TObject) ofobject;
后面的of object就是表示处理这个事件的过程应该是一个对象的方法。因为事件是属于对象的,所以处理事件的过程应该也是对象的方法才对。所以不能用单元的全局过程来作。
我理解你的想法,大概是觉得处理整个程序的事件的代码不适合写在某个窗体里。如果你想要把相关代码整理在一起,可以单独写一个对象包含所有的处理工程事件的代码即可,不需要一定是窗口的方法。
另外你可以用Applications控件放在一个DataModule中处理工程事件,可以不用自己写那些事件的关联代码。
type
TMyDrawHint=procedure (Sender:TObject) of object;
var
MyDrawHint:TMyDrawHint;
procedure TForm1.Oncreate(Sender:TObject);
begin
application.onhint:=MyDrawHint;
end;
end;
这样编译不出错了,但是事件永远不会发生,为什么呢?
只是声明
MyDrawHint是一个空值
建议多看以下书
1,事件是一个指向方法的指针,也就是说实现它的应该是类的一个方法。这个上面已经解释的比较清楚了。
2,property是定义属性的语句,property的具体写法和含义,看看帮助应该就可以明白了。或者查一下论坛,最近还有讨论的帖子。在这里你可以认为事件属性就是一个指针值即可。
3,函数指针的概念。不清楚你对指针是否明白。函数指针和一般的指针基本类似,只不过不能通过New来给指针创建实例,只能把已有的函数实体附给它。如:
type
MyPoc = procedure(var I: Integer);
procedure add(var I: Integer);
begin
I := I + 1;
end;
procedure Sub(var I: Integer);
begin
I := I - 1;
end
var
p: MyPoc;
i: Integer;
begin
i := 1;
p(i); //出错,调用空指针
p = Add;
p(i); //add(i);
p = Sub;
p(i); //Sub(i);
end;
现在回头看你刚才问的问题,你不过是把一个指针指向另一个指针的地址,但是另一个指针还是空指针,所有不会执行(不出错是因为代码中会先判断指针不为空才调用)。另一方面我觉得你的问题问的很奇怪啊。根本就没有处理事件的代码,你希望会发生什么呢?
书籍方面,推荐Delphi5(6)开发人员指南,全面又不失深度,相当的不错。
至于OOP编程思想,这个和是不是用Delphi没有太大关系,应该阅读相关书籍来掌握。这方面书籍很多,针对的层面也不相同,《面向对象软件开发教程》似乎不错,李维将要出版的《Inside VCL》应该也很值得期待。