2011-11-04 17 views
31

Mac OSとWindowsを対象としたDelphi XE2アプリケーションを開発中です。コンテキストメニューに統合したいと思っています。ウィンドウの場合、これは簡単な作業です。しかし、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するMac OSのアプリケーションhungsでこれを実行し、時には 'でクラッシュ

<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> 

バスエラー '例外が発生します。

誰でもこの問題を解決できますか?

または、おそらくDelphi XE2はこの種の機能をサポートしていませんか?

+3

関連する質問Cocoa + ObjectiveCを使用していると仮定して、DelphiXE2/Firemonkeyを使用して、ココア/オブジェクトCメッセージベースのAPIを呼び出すことができます。http://stackoverflow.com/questions/9420361/add-an-item -infinders-contextual-menu-with-cocoa - 私は、Cocoa/ObjectiveCを使用して全体の制作サービスのビットを書いて、あなたのdelphiアプリからそのネイティブなobjectiveC共有ライブラリを単に呼び出す方法を見つけようとします。 –

+0

XE2はOSX用のフリーパスカルを使用しているため、実行可能であれば、無料のパスカルのドキュメントやフォーラムで見つけることができます。そして、フリーパスカルはOSX上でずっとずっと続いていたので、私はそれがDelphiフォーラム以上のものになると確信しています。 – adrianj98

答えて

1

私はあなたがあなた自身のNSApplicationオブジェクトを割り当てている2つの潜在的な問題

  1. を参照してください。私はこれが正しいことを疑う - デルファイは内部的にもそれを作成しないのだろうか?たとえそうでなくても、メッセージを実際に処理できるようにするには、ある時点でのrunメソッドを入力する必要があります。

  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 - Delphiのブリッジ作業のために必要だと思う)作成しました:

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

をこのインターフェイスからTMessageProviderを継承しましたTOCLocalクラスです。

この後、私のアプリはコンテキストメニューからのサービスリクエストに反応します。

私は自分のプロジェクトのソースを共有しました。 Hereです。

関連する問題