我正在开发针对Mac OS和Windows的Delphi XE2应用程序。我希望集成到上下文菜单中。对于Windows,这是一项简单的任务。但对于Mac OS,我不知道该怎么做。
我已阅读Providing a Service文档并在Delphi中尝试了类似的代码,但没有运气。
查看Finder集成试验的简单代码。
App.dpr
program App;
uses
SysUtils,
{$IFDEF MACOS}
AppKit, CocoaTypes, CoreFoundation,
CoreServices, Foundation, Mach, ObjCRuntime,
ObjectiveC, OCMarshal, OpenGL, QuartzCore, Security,
SystemConfiguration,
{$ENDIF}
MessageProvider;
{$IFDEF MACOS}
var
app: NSApplication;
provider: TMessageProvider;
{$ENDIF}
begin
Application.Initialize;
{$IFDEF MACOS}
provider := TMessageProvider.Create();
app := TNSApplication.Alloc();
app.setServicesProvider(provider);
{$ENDIF}
Application.CreateForm(TFormOSVersion, FormOSVersion);
Application.Run;
end.
MessageProvider.pas
unit MessageProvider;
interface
uses
FMX.Dialogs
{$IFDEF MACOS}
, AppKit, CocoaTypes, CoreFoundation,
CoreServices, Foundation, Mach, ObjCRuntime,
ObjectiveC, OCMarshal, OpenGL, QuartzCore, Security,
SystemConfiguration
{$ENDIF}
;
type
TMessageProvider = class
public
procedure simpleMessage(var userData: string; var error: string);
end;
implementation
procedure TMessageProvider.simpleMessage(var userData: string; var error: string);
begin
ShowMessage('Simple message from service.');
error := '';
end;
end.
为info.plist添加了配置
<key>NSServices</key>
<array>
<dict>
<key>NSKeyEquivalent</key>
<dict>
<key>default</key>
<string>e</string>
</dict>
<key>NSMenuItem</key>
<dict>
<key>default</key>
<string>App/Message</string>
</dict>
<key>NSMessage</key>
<string>simpleMesage</string>
<key>NSPortName</key>
<string>App</string>
</dict>
</array>
在Mac OS应用程序上运行时,挂起并且有时会因“总线错误”异常而崩溃。
有人可以帮忙解决这个问题吗?
或许Delphi XE2不支持这种功能?
答案 0 :(得分:2)
最后,我回到了这个项目并成功注册了服务提供商并处理了服务请求。
首先我尝试使用NSRegisterServicesProvider方法,但Macapi源中没有这样的方法,所以我搜索了applicationDidFinishLaunching委托。使用它我注册了我的服务提供商:
procedure TApplicationDelegate.applicationDidFinishLaunching(Notification: Pointer);
var
autoReleasePool: NSAutoreleasePool;
app: NSApplication;
provider: TMessageProvider;
begin
autoReleasePool := TNSAutoreleasePool.Create;
try
autoReleasePool.init();
app := TNSApplication.Wrap(TNSApplication.OCClass.sharedApplication);
provider := TMessageProvider.Create();
app.setServicesProvider(provider.ObjId);
finally
autoReleasePool.release();
end;
end;
我也为服务提供商创建了接口(我认为它是ObjectiveC-Delphi桥接工作所必需的):
IMessageProvider = interface(IObjectiveC)['{1EA9319A-8F99-4445-B435-48D5E73876FA}']
procedure simpleMessage(pBoard: Pointer; userData: Pointer; error: PPointer); cdecl;
end;
并从此接口和TOCLocal类继承了TMessageProvider。
在此之后,我的应用程序可以对上下文菜单中的服务请求做出反应。
我已经分享了我的项目来源。 Here他们是。
答案 1 :(得分:1)
我看到两个潜在的问题
您正在分配自己的NSApplication
对象。我怀疑这是正确的 - Delphi内部也没有创建一个吗?即使它没有,您可能需要在某个时刻输入NSApplication
的{{1}}方法,以使其能够实际处理消息。
服务提供商必须使用run
委托方法进行注册。您在创建applicationDidFinishLaunching:
实例后立即尝试注册它。
如果您使用NSApplication
注册服务提供商,而不是使用NSRegisterServicesProvider(id provider, NSString *portName)
的{{1}},我认为您可以避免这两个问题。