2011-11-04 14 views
31

Sto lavorando all'applicazione Delphi XE2 destinata a Mac OS e Windows. E voglio avere l'integrazione nel menu contestuale. Per Windows questo è un compito semplice. Ma per Mac OS non so come farlo.Come aggiungere voci di menu a Mac OS Finder in Delphi XE2

Ho letto la documentazione Providing a Service e ho provato un codice simile in Delphi ma senza fortuna.

Consulta il codice semplice per le prove di integrazione di 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. 

configurazione Aggiunto a 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> 

Quando eseguire questo su hungs applicazione per Mac OS e, a volte si blocca con ' Errore bus error '.

Qualcuno può aiutare con questo problema?

O forse Delphi XE2 non supporta questo tipo di funzionalità?

+3

La domanda correlata che si presume che si stia utilizzando Cocoa + ObjectiveC, potrebbe essere adattata, utilizzando l'abilità DelphiXE2/Firemonkey per richiamare le API basate su messaggi cocoa/objectiveC: http://stackoverflow.com/questions/9420361/add-an-item -in-finder-contextual-menu-with-cocoa - Sarei tentato di scrivere l'intero bit dei servizi di creazione usando Cocoa/ObjectiveC e trovare un modo per poi semplicemente richiamare quella libreria condivisa oggettivo nativo dalla tua app delphi. –

+0

Penso che se è fattibile lo troverai nella documentazione o nei forum gratuiti pascal dato che XE2 usa pascal gratuito per OSX. E dal momento che free pascal è stato su OSX per molto tempo sono sicuro che avrà più dei forum di Delphi. – adrianj98

risposta

1

vedo due potenziali problemi

  1. si assegnano il proprio NSApplication oggetto. Dubito che questo sia corretto - Delphi non ne crea uno anche internamente? E anche se così non fosse, probabilmente dovresti inserire il metodo run a un certo punto per renderlo effettivamente in grado di gestire i messaggi.

  2. I provider di servizi devono essere registrati nel metodo delegato applicationDidFinishLaunching:. Si tenta di registrarlo immediatamente dopo aver creato l'istanza NSApplication.

Penso che si possa evitare di entrambi i problemi se si utilizza NSRegisterServicesProvider(id provider, NSString *portName) per registrare il servizio fornito, invece di utilizzare NSApplication s' setServicesProvider:.

+0

Ho avuto pensieri simili sul primo oggetto. E, come ricordo, stavo cercando un modo per ottenere oggetto NSApplication da TApplication. Proverò il metodo NSRegisterServicesProvider quando tornerò a quel progetto. Come ho capito, questo metodo dovrebbe essere chiamato proprio prima del metodo Application.Run? – GothAr

2

Infine, sono tornato a questo progetto e ho registrato con successo il fornitore di servizi e ho gestito la richiesta di assistenza.

Prima di tutto ho provato a utilizzare il metodo NSRegisterServicesProvider, ma non esiste un metodo simile nei sorgenti Macapi, quindi ho cercato applicationDidFinishLaunching delegate. Usandolo Ho registrato il mio fornitore di servizi:

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; 

Inoltre ho creato un'interfaccia per fornitore di servizi (penso che è necessario per ObjectiveC-Delphi lavoro ponte):

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

ed ereditato TMessageProvider da questa interfaccia e classe TOCLocal.

Dopo questa mia app può rispondere alla richiesta di servizio dal menu di scelta rapida.

Ho condiviso le fonti del mio progetto. Here sono.

Problemi correlati