簡體   English   中英

如何在Delphi XE2中將菜單項添加到Mac OS Finder

[英]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。

在此之后我的應用程序可以從上下文菜單響應服務請求。

我已經分享了我的項目來源。 他們在這里

我看到兩個潛在的問題

  1. 您正在分配自己的NSApplication對象。 我懷疑這是正確的 - Delphi內部也沒有創建一個嗎? 即使它沒有,你可能需要在某個時候輸入NSApplicationrun方法,以使它實際上能夠處理消息。

  2. 服務提供者必須在applicationDidFinishLaunching: delegate方法中注冊。 您嘗試在創建NSApplication實例后立即注冊它。

我認為如果您使用NSRegisterServicesProvider(id provider, NSString *portName)來注冊您的服務提供,而不是使用NSApplicationsetServicesProvider:我可以避免這兩個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM