[英]Howto add menu item to Mac OS Finder in Delphi XE2
我正在研究面向Mac OS和Windows的Delphi XE2應用程序。 我希望集成到上下文菜單中。 對於Windows,這是一項簡單的任務。 但對於Mac OS,我不知道該怎么做。
我已閱讀提供服務文檔並在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不支持這種功能?
最后,我回到了這個項目並成功注冊了服務提供商並處理了服務請求。
首先我嘗試使用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。
在此之后我的應用程序可以從上下文菜單響應服務請求。
我已經分享了我的項目來源。 他們在這里 。
我看到兩個潛在的問題
您正在分配自己的NSApplication
對象。 我懷疑這是正確的 - Delphi內部也沒有創建一個嗎? 即使它沒有,你可能需要在某個時候輸入NSApplication
的run
方法,以使它實際上能夠處理消息。
服務提供者必須在applicationDidFinishLaunching:
delegate方法中注冊。 您嘗試在創建NSApplication
實例后立即注冊它。
我認為如果您使用NSRegisterServicesProvider(id provider, NSString *portName)
來注冊您的服務提供,而不是使用NSApplication
的setServicesProvider:
我可以避免這兩個問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.