领略TApplicationEvents的风采
这是它的声明,它的数据成员全部都是Event,而没有真正意义上的数据(如此一来,几乎可以猜测,它本身什么都做不了):
TCustomApplicationEvents = class(TComponent)
private
FOnActionExecute: TActionEvent;
FOnActionUpdate: TActionEvent;
FOnException: TExceptionEvent;
FOnMessage: TMessageEvent;
FOnHelp: THelpEvent;
FOnHint: TNotifyEvent;
FOnIdle: TIdleEvent;
FOnDeactivate: TNotifyEvent;
FOnActivate: TNotifyEvent;
FOnMinimize: TNotifyEvent;
FOnRestore: TNotifyEvent;
FOnShortCut: TShortCutEvent;
FOnShowHint: TShowHintEvent;
FOnSettingChange: TSettingChangeEvent;
FOnModalBegin: TNotifyEvent;
FOnModalEnd: TNotifyEvent;
procedure DoActionExecute(Action: TBasicAction; var Handled: Boolean);
procedure DoActionUpdate(Action: TBasicAction; var Handled: Boolean);
procedure DoActivate(Sender: TObject);
procedure DoDeactivate(Sender: TObject);
procedure DoException(Sender: TObject; E: Exception);
procedure DoIdle(Sender: TObject; var Done: Boolean);
function DoHelp(Command: Word; Data: Longint; var CallHelp: Boolean): Boolean;
procedure DoHint(Sender: TObject);
procedure DoMessage(var Msg: TMsg; var Handled: Boolean);
procedure DoMinimize(Sender: TObject);
procedure DoRestore(Sender: TObject);
procedure DoShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: THintInfo);
procedure DoShortcut(var Msg: TWMKey; var Handled: Boolean);
procedure DoSettingChange(Sender: TObject; Flag: Integer; const Section: string; var Result: Longint);
procedure DoModalBegin(Sender: TObject);
procedure DoModalEnd(Sender: TObject);
protected
property OnActionExecute: TActionEvent read FOnActionExecute write FOnActionExecute;
property OnActionUpdate: TActionEvent read FOnActionUpdate write FOnActionUpdate;
property OnActivate: TNotifyEvent read FOnActivate write FOnActivate;
property OnDeactivate: TNotifyEvent read FOnDeactivate write FOnDeactivate;
property OnException: TExceptionEvent read FOnException write FOnException;
property OnIdle: TIdleEvent read FOnIdle write FOnIdle;
property OnHelp: THelpEvent read FOnHelp write FOnHelp;
property OnHint: TNotifyEvent read FOnHint write FOnHint;
property OnMessage: TMessageEvent read FOnMessage write FOnMessage;
property OnMinimize: TNotifyEvent read FOnMinimize write FOnMinimize;
property OnRestore: TNotifyEvent read FOnRestore write FOnRestore;
property OnShowHint: TShowHintEvent read FOnShowHint write FOnShowHint;
property OnShortCut: TShortCutEvent read FOnShortCut write FOnShortCut;
property OnSettingChange: TSettingChangeEvent read FOnSettingChange write FOnSettingChange;
property OnModalBegin: TNotifyEvent read FOnModalBegin write FOnModalBegin;
property OnModalEnd: TNotifyEvent read FOnModalEnd write FOnModalEnd;
public
constructor Create(AOwner: TComponent); override;
procedure Activate;
procedure CancelDispatch;
end;
它的构造函数平淡无奇:
constructor TCustomApplicationEvents.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
if Assigned(MultiCaster) then
MultiCaster.AddAppEvent(Self);
end; procedure TMultiCaster.AddAppEvent(AppEvent: TCustomApplicationEvents);
begin
if FAppEvents.IndexOf(AppEvent) = - then
FAppEvents.Add(AppEvent);
end;
它的秘密在于:一旦使用了这个控件,那么就会引入AppEvents单元,因此会执行:
initialization
GroupDescendentsWith(TCustomApplicationEvents, Controls.TControl);
MultiCaster := TMultiCaster.Create(Application);
end.
其中GroupDescendentsWith函数来自classes.pas单元:
procedure GroupDescendentsWith(AClass, AClassGroup: TPersistentClass);
begin
RegGroups.Lock;
try
RegGroups.GroupWith(AClass, AClassGroup);
finally
RegGroups.Unlock;
end;
end;
而MultiCaster是AppEvents.pas的全局变量:
var
MultiCaster: TMultiCaster = nil;
其实就是靠创建MultiCaster的时候进行对接:
constructor TMultiCaster.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FAppEvents := TComponentList.Create(False);
with Application do
begin
OnActionExecute := DoActionExecute;
OnActionUpdate := DoActionUpdate;
OnActivate := DoActivate;
OnDeactivate := DoDeactivate;
OnException := DoException;
OnHelp := DoHelp;
OnHint := DoHint;
OnIdle := DoIdle;
OnMessage := DoMessage;
OnMinimize := DoMinimize;
OnRestore := DoRestore;
OnShowHint := DoShowHint;
OnShortCut := DoShortcut;
OnSettingChange := DoSettingChange;
OnModalBegin := DoModalBegin;
OnModalEnd := DoModalEnd;
end;
end;
它对消息的处理就是转发,这里举三个例子(OnMessage,OnMinimize,OnException):
procedure TCustomApplicationEvents.DoMessage(var Msg: TMsg; var Handled: Boolean);
begin
if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
end; procedure TMultiCaster.DoMessage(var Msg: TMsg; var Handled: Boolean);
var
I: Integer;
begin
BeginDispatch;
try
for I := Count - downto do
begin
AppEvents[I].DoMessage(Msg, Handled);
if FCancelDispatching then Break;
end;
finally
EndDispatch;
end;
end; procedure TCustomApplicationEvents.DoMinimize(Sender: TObject);
begin
if Assigned(FOnMinimize) then FOnMinimize(Sender);
end; procedure TMultiCaster.DoMinimize(Sender: TObject);
var
I: Integer;
begin
BeginDispatch;
try
for I := Count - downto do
begin
AppEvents[I].DoMinimize(Sender);
if FCancelDispatching then Break;
end;
finally
EndDispatch;
end;
end; procedure TCustomApplicationEvents.DoException(Sender: TObject;
E: Exception);
begin
if not (E is EAbort) and Assigned(FOnException) then
FOnException(Sender, E)
end; procedure TMultiCaster.DoException(Sender: TObject; E: Exception);
var
I: Integer;
FExceptionHandled: Boolean;
begin
BeginDispatch;
FExceptionHandled := False;
try
for I := Count - downto do
begin
if Assigned(AppEvents[I].OnException) then
begin
FExceptionHandled := True;
AppEvents[I].DoException(Sender, E);
if FCancelDispatching then Break;
end;
end;
finally
if not FExceptionHandled then
if not (E is EAbort) then
Application.ShowException(E);
EndDispatch;
end;
end;
其实就是这么简单,这个AppEvents.pas单元连finalization模块都没有。。。
不过说真的,这个控件简单实用,在看它的析构函数的时候,我忽然有点明白了,为什么TApplication要处理这么多消息,原本它应该没有机会处理的嘛:
destructor TMultiCaster.Destroy;
begin
MultiCaster := nil;
with Application do
begin
OnActionExecute := nil;
OnActionUpdate := nil;
OnActivate := nil;
OnDeactivate := nil;
OnException := nil;
OnHelp := nil;
OnHint := nil;
OnIdle := nil;
OnMessage := nil;
OnMinimize := nil;
OnRestore := nil;
OnShowHint := nil;
OnShortCut := nil;
OnSettingChange := nil;
OnModalBegin := nil;
OnModalEnd := nil;
end;
FAppEvents.Free;
inherited Destroy;
end;
最后还发现,TApplicationEvents终于也不甘示弱,终于自己处理了一个消息,这可真是不容易呀。但是我搞不明白,为什么会有这里例外,而且在TMultiCaster里同样有定义:
procedure TCustomApplicationEvents.DoHint(Sender: TObject);
begin
if Assigned(FOnHint) then
FOnHint(Sender)
else
with THintAction.Create(Self) do
try
Hint := Application.Hint;
Execute;
finally
Free;
end;
end; procedure TMultiCaster.DoHint(Sender: TObject);
var
I: Integer;
begin
BeginDispatch;
try
for I := Count - downto do
begin
AppEvents[I].DoHint(Sender);
if FCancelDispatching then Break;
end;
finally
EndDispatch;
end;
end;
领略TApplicationEvents的风采的更多相关文章
- 2016-08-01一起领略ReactJs的风采
现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...
- Java大神带你领略queue的风采
作为数据结构中比较常见的类型,你足够了解队列(queue)吗?从今天开始,我将为你讲解关于队列(queue)的一切,包括概念.类型和具体使用方法,如果你对此足够感兴趣,赶快来加入我们,我将同你一起探索 ...
- 一看就懂的ReactJs入门教程-精华版
现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...
- 在windows下安装gulp —— 基于 Gulp 的前端集成解决方案(一)
相关连接导航 在windows下安装gulp —— 基于 Gulp 的前端集成解决方案(一) 执行 $Gulp 时发生了什么 —— 基于 Gulp 的前端集成解决方案(二) 常用 Gulp 插件汇总 ...
- ECMAScript 6教程 (一)
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文连接,博客地址为 http://www.cnblogs.com/jasonnode/ .该系列课程是 ...
- ReactJs入门教程
现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...
- 一看就懂的ReactJs入门教程(精华版)
一看就懂的ReactJs入门教程(精华版) 现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和 ...
- Windows下FFmpeg快速入门
本系列文章导航 Windows下FFmpeg快速入门 ffmpeg参数解释 mencoder和ffmpeg参数详解(Java处理视频) Java 生成视频缩略图(ffmpeg) 使用ffmpeg进行视 ...
- 对React的理解
转自:http://www.cocoachina.com/webapp/20150721/12692.html 现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了R ...
随机推荐
- 在windows下安装mysql5.6.24版本
链接地址:http://jingyan.baidu.com/article/90bc8fc8615c99f653640cc4.html 工具/原料 官网下载安装包 系统需装net 4.0及以上运行库 ...
- android用户界面之ScrollView教程实例汇总
--------------------------汇总不容易啊------------------------------- 一.ScrollView基础知识 1.Android中ScrollVie ...
- LoadRunner脚本增强
1.检查点 web_find() 和web_reg_find() 2.Block技术 如果对不同的事物进行不同次数的循环该怎么处理?默认情况下LoadRunner对所有的事物都是统一执行的,即虽然有多 ...
- HNCU1741:算法3-2:行编辑程序
http://hncu.acmclub.com/index.php?app=problem_title&id=111&problem_id=1741 题目描述 一个简单的行编辑程序的功 ...
- 【COCOS2D-HTML5 开发之三】演示样例项目附源代码及执行的GIF效果图
本站文章均为李华明Himi原创,转载务必在明显处注明:(作者新浪微博:@李华明Himi) 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/cocos2d- ...
- meanShift算法介绍
meanShift,均值漂移,在聚类.图像平滑.切割.跟踪等方面有着广泛的应用.meanShift这个概念最早是由Fukunage在1975年提出的,其最初的含义正如其名:偏移的均值向量:但随着理论的 ...
- Swift - 使用NSURLSession同步获取数据(通过添加信号量)
过去通过 NSURLConnection.sendSynchronousRequest() 方法能同步请求数据.从iOS9起,苹果建议废除 NSURLConnection,使用 NSURLSessio ...
- textarea内容有换行时存入数据库丢失问题的解决 (转载)
http://blog.csdn.net/zhang_j_h/article/details/44563167 存入: function GetInputData(id, cmd) { var pos ...
- 多图片/文件上传 - SwfUpload/PlUpload
<文件上传利器SWFUpload使用指南> <前端上传组件Plupload使用指南>
- 每周日与周四《红酒屋》探戈舞会"Wine Bar" Milonga_原生态拉丁_新浪博客
每周日与周四<红酒屋>探戈舞会"Wine Bar" Milonga_原生态拉丁_新浪博客 每周日与周四<红酒屋>探戈舞会"Wine Bar ...