首先,我们要知道 QPlugins 的通知机制使用了订阅发布模式。一个通知或叫主题有两个重要的属性:
- 名称(Name)
名称是通知类型的名字,必需在整个插件系统中保证唯一,同名的被认为是一个类型的通知。当跨进程通信时,是靠名称而不是 ID 来唯一区分通知。 - 编号(ID)
一个进程唯一的编号(为什么是进程唯一,这个问题好高难,所以不知道如何回答),这个ID是一个整数,从0开始,在你调用 IdByName 获取 ID 时生成,这个 ID 无论注册多少次,都会返回同一个值。但是,这个值不跨进程,所以不能用于在网络或多进程间广播通知。
好了,既然是订阅发布模式,那么,我们就只需要在对通知感兴趣的地方,调用订阅的接口来订阅通知。我们分成两个部分来说这下事。
1、订阅者需要实现 IQNotify 接口,下面是一个简单的例子:
type TMyHandler=class(IQNotify) procedure Notify(const AId: Cardinal; AParams: IQParams; var AFireNext: Boolean); stdcall; end;
这里有三个参数,咱们来简单解释一下:
- AId:订阅者收到的通知编号
- AParams : 订阅者收到的通知附加的参数信息,具体内容由通知的发布者决定
- AFireNext:是否允许通知管理器发送通知给下一个订阅者
然后你创建一个 TMyHandler 的实例,用来接收通知,大概意思是:
var AMgr:IQNotifyManager; begin AMgr:=PluginsManager as IQNotifyManager; FNotifyId:=AMgr.IdByName('通知名称'); AMgr.Subscribe(FNotifyId,TMyHandler.Create); ...
如果是 DLL 或 BPL 中的插件,你需要在模块卸载时,调用 IQNotifyManager.Unsubscribe 来取消订阅,否则可能会出 AV 错误。这里就不在缀述。
2、发布者
好吧,我承认发布者最不负责任,它不需要处理通知发布后的结果,它只是负责发通知。同样的,第一步,通过 IdByName 来获取指定的通知 ID,然后只需要调用 IQNotifyManager.Send 或 Post 方法来发布通知,二者的区别就象 SendMessage 和 PostMessage 一样。
(PluginsManager as IQNotifyManager).Send(FNotifyId,通知的参数);
OK,发布者不需要任何清理工具,因为发布完就没它什么事了。我们看一个例子的执行效果: