2011-11-04 83 views
31

我正在開發面向Mac OS和Windows的Delphi XE2應用程序。我想要集成到上下文菜單中。對於Windows來說,這是一件簡單的事但對於Mac OS我不知道如何做到這一點。如何將菜單項添加到Delphi XE2中的Mac OS Finder

我讀過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上應用hungs運行此有時用「崩潰總線錯誤「異常。

任何人都可以幫助解決這個問題嗎?

或者Delphi XE2不支持這種功能?

+3

相關問題假設您使用Cocoa + ObjectiveC,可以使用DelphiXE2/Firemonkey調用基於cocoa/objectiveC消息的API來調整:http://stackoverflow.com/questions/9420361/add-an-item -in-finders-contextual-menu-with-cocoa - 我會試圖用Cocoa/ObjectiveC編寫整個製作服務位,然後找到一種方法,然後從你的delphi應用程序簡單地調用本地的objectiveC共享庫。 –

+0

我認爲如果它是可行的,你會在免費的pascal文檔或論壇中找到它,因爲XE2使用免費的pascal for OSX。由於免費的pascal已經在OSX上很長時間了,我相信它會比Delphi論壇更多。 – adrianj98

回答

1

我看到兩個潛在的問題

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

  2. 服務提供商必須註冊applicationDidFinishLaunching:委託方法。嘗試在創建NSApplication實例後馬上註冊它。

我認爲你能避免這兩個問題,如果您使用NSRegisterServicesProvider(id provider, NSString *portName)註冊您的服務提供,而不是使用NSApplicationsetServicesProvider:

+0

我對第一件物品有類似的想法。而且,正如我記得的那樣,我正在尋找一些方法來從TApplication獲取NSApplication對象。當我返回到該項目時,我會嘗試使用NSRegisterServicesProvider方法。據我所知,這個方法應該在Application.Run方法之前調用? – GothAr

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德爾福工作橋):

IMessageProvider = interface(IObjectiveC)['{1EA9319A-8F99-4445-B435-48D5E73876FA}'] 
    procedure simpleMessage(pBoard: Pointer; userData: Pointer; error: PPointer); cdecl; 
end; 

和繼承TMessageProvider從這個接口和TOCLocal類。

之後,我的應用程序可以對來自上下文菜單的服務請求作出反應。

我已經分享了我的項目的來源。他們是Here

相關問題