- What defines a plug-in?(什么定义了一个插件)
- 1.PiPL资源
- 2.Plug-in management(插件管理)
- 2.1Plug-in entry point and message(插件入口和消息)
- 2.2Reload and unload messages(加载和卸载消息)
- 2.3Start-up and shut-down message(启动和关闭消息)
- 3.Notifiers(通告)
- 3.1Handling callers and selectors
- 3.2Message data(消息内容)
- 4.作者答疑
在Windows中,插件在DLL中。Illustrator插件有以下特性:
- 文件后缀为.aip,如CoolEffect.aip。
- 正确的插件PiPL资源。PiPL资源包含了插件的信息。Illustrator认为只有那些有PiPL资源的插件有可能是插件。有正确属性的文件被加载到插件列表。
- 代码入口包含可以在目标平台上运行二进制代码。入口点在PiPL资源中指定,调用时有许多消息描述哪个动作去执行。
Plug-in property list(PiPL)资源包含被Illustrator插件管理器使用的属性,包括:插件类型(kind);插件代码调用机制(ivrs);入口点(code descriptor)。Illustrator认为包含有正确PiPL的文件才可能为插件。PiPL属性使用本地平台资源定义。
2.Plug-in management(插件管理)当illustrator初始化启动时,只有拥有正确PiPL和代码入口的插件才能被识别。每一个插件在需要时从内存中加载或卸载。插件需要在假设它不会总是在内存的前提上编写。这也导致插件需要在卸载和重新加载时保存和恢复状态信息。插件可以从应用程序得到一些服务。由于插件可能被卸载,illustrator提供了存储重要数据的方法。每次插件调用时,会给出足够的信息来完成动作的执行。 当一个插件的资源需要另外一个插件提供时,加载顺序就变得很重要,因为提供资源的插件需要首先加载。正如上面提到的,插件导出时在PiPL资源中需要声明一个或多个suites.illustrator在加载和执行插件时,使用这些信息,确认suites和其他资源是否可用。
2.1Plug-in entry point and message(插件入口和消息) 加载插件代码到内存中时,Illustrator插件管理与你的插件进行着通信,如果必要,会调用PiPL代码描述属性中入口点。约定上,入口点叫做PluginMain,以C语言方式编译链接: Extern “C” ASAPI ASErr PluginMain(char caller, char selector, void* message);** 三个参数被传给PluginMain函数。他们共同构成了一个消息。前两个参数表示了消息动作,描述了插件功能。第三个参数是一个指向数据结构的指针,根据消息动作不同而不同。当你决定了消息动作,可以转换消息数据参数到需要的类型。 Message actions:callers and selectors(消息动作:调用者和选择器)。每次插件调用时,会从illustrator收到消息动作。消息动作通知插件事件发生了,插件需要执行对应的动作。传递给插件的消息动作包含2个标识符: **Caller指示消息的发送者(PICA,宿主程序或插件)和动作的通用类型。Slector指定动作类型的执行动作。**所有插件收到至少4类消息动作:reload(重新加载),unload(卸载),startup(启动)和shutdown(关系)。此外,插件可能收到特定插件类型的附加消息。如,illustrator发送给插件菜单消息,它基于2个字符串,当由插件添加的菜单项被点击时: #define kSPAccessCaller “SP Access” #define kSPAccessUnloadSelector “Unload” #define kSPAccessReloadSelector “Reload” 调用和选择标志是C字符串。按照约定,每一个调用字符串都有一个前缀。这样新的消息动作,可以被其他应用程序和插件轻松定义,极少产生冲突。如,illustrator使用AI作为前缀,PICA则采用SP作为前缀。消息动作用来指定插件感兴趣的事件。
不论插件家载入内存或从内存卸载,illustrator发送access消息动作。 #define kSPAccessCaller “SP Access” #define kSPAccessUnloadSelector “Unload” #define kSPAccessReloadSelector “Reload” 消息包括access caller和a reload或unload selector。这是你的插件的执行安装,恢复和保存状态信息的时机。Access caller/selector排除了其他callers和selectors。Access消息排除了其他消息。Reload是你的插件首先收到的消息。Unload是最后一个。在这个过程中,你的插件必须请求和释放suites,除了那些建入了illustrator中的。
2.3Start-up and shut-down message(启动和关闭消息)当插件与程序交互时,Illustrator有两个核心的接口消息动作。 #define kSPInterfaceCaller “SP Interface” #define kSPInterfaceStartupSelector “Startup” #define kSPInterfaceShutdownSelector “Shutdown” 当illustrator启动时,发送给每一个它能找到的插件一个Startup消息。这样可以使插件分配全局内存,添加用户接口,注册suites,执行其他初始化。启动消息包括interface caller(kSPInterfaceCaller)和start-up selector(kSPInterfaceStartupSelector)。 当用户退出illustrator时,它发送每个插件一个shutdown消息。启动消息包括interface caller(kSPInterfaceCaller)和start-up selector(kSPInterfaceStartupSelector)。关闭用来更新文件,保存参数,不是简单的销毁。导出suite的插件不能销毁插件全局变量和suite信息,因为它关闭后,可能被其他插件关闭时调用。如,你的插件实现一个preferences suite被其他插件使用,可能在你关闭后,他们关闭处理时仍然要调用。
3.Notifiers(通告)一些动作消息同样被归于通告。指示用户改变了illustrator的一些东西。如,用户选择了一个对象。插件必须注册它们感兴趣的通告。Notifier suite用来注册或移除通告请求(参看AINotifierSuite)。插件同样可以创建它们自身的通告,用来向其他插件广播变化。
3.1Handling callers and selectors你的插件管理很大程度上基于收到的消息。通常,你的插件必须通过caller和selector参数来决定消息动作。如:
extern "C" ASAPI ASErr PluginMain(char *caller, char *selector, void *message)
{
ASErr error = kNoErr;
if( strcmp( caller, kspAccessCaller ) == 0 )
{
if( strcmp( selector, kspAccessReloadSelector ) == 0)
error = MyRestorGlobals( message );
else if( strcmp ( selector, kspAccessUnloadSelector ) == 0)
error = MySaveGlobals( message );
}
else if( strcmp( caller, kspInterfaceCaller) == 0)
{
if( strcmp ( selector, kSPInterfaceStartupSelector) == 0)
{
error = MyStartupPlugin( message );
}
else if( strcmp( selector, kSPInterfaceShutdownSelector) == 0)
{
error = MyShutdownPlugin( message );
}
}
else if( strcmp ( caller, kCallerAIMenu ) == 0) && strcmp( selector, kSelectorAIGoMenuItem) == 0) )
error = MyHandleMenu( message);
}
}
3.2Message data(消息内容)
最后一个传入你插件入口点的指针是一个消息数据结构体,它包括这个消息动作的相关信息。如,当一个鼠标点击消息接收到时,消息结构体包括鼠标的位置。消息结构体的内容取决于消息,在你的插件定义这个后,才能知道。由于消息内容不同,按照约定,所有消息结构体由相同字段组成,组合到SPMessageData结构体中。
typedef struct SPMessageData
{
long SPCheck;
struct SPPlugin *self;
void *globals;
struct SPBasicSuite *basic;
} SPMessageData;
如果是有效的消息,SPCheck字段包含kSPValidSPMessageData。self字段是被调用插件的引用。用来添加插件suites,adapters和其他插件数据给illustrator。Illustrator用附加数据存储这些值。如有必要,它可以用来重新调用你的插件。**globas指针被你的插件用来保存需要的调用信息。**通常,它是一个指向你插件启动时分配的一块内存。当你的插件卸载时,这个值被illustrator保存,调用插件时,又装回到插件中。插件利用这个块来保存在卸载和装载间的任何需要保持的状态信息。 注意:很重要的是globas是用illustrator的内存分配API来分配的。否则,当插件卸载时,内存可能被操作系统释放。basic字段是指向Basic suite的指针(参看 SPBasicSuite),它可以允许你的插件请求其他suites和提供基本的内存管理。当illustartor或插件想要发送一个消息到你的插件时,它传递一个对应的消息数据结构体。下面有一些例子。
CallerMessage typeDescritionkSPAccessCallerSPAccessMessageContains SPMessageDatakSPInterfaceCallerSPInterfaceMessageContains SPMessageDatakCallerAIMenuAIMenuMessageContains SPMessageData and a reference to a menu item that was chosenif ( strcmp ( caller, kSPAccessCaller) == 0)
{
SPAccessMessage *accessMsg = static_cast(message);
// access accessMsg
}
else if( strcmp( caller, kSPInterfaceCaller) == 0 )
{
SPInterfaceMessage *interfaceMsg = static_cast(message);
// access interfaceMsg
}
else if( strcmp( caller, kCallerAIMenu ) == 0)
{
AIMenuMessage *menuMsg = static_cast(message);
// access menuMsg;
}
4.作者答疑
代码长度过长,如需全部项目,请留言。
提示: 作者知了-联系方式1 提示: 作者知了-联系方式2