将我的应用与其在OSX中的自定义文件类型相关联,然后双击打开文件 [英] Associate my app with its custom file type in OSX and open file on double click

查看:83
本文介绍了将我的应用与其在OSX中的自定义文件类型相关联,然后双击打开文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的FMX应用程序(例如MyApp)使用其自己的自定义文件类型来存储数据文件.假设这些文件的扩展名为* .myext.

My FMX app (MyApp, say) uses its own custom file type to store data files. Let's say these files have extension *.myext.

我设法设置了info.plist,以便OSX将MyApp注册为文件类型* .myext的所有者.

I have managed to set up the info.plist so that OSX registers MyApp as the owner of file type *.myext.

如果MyApp尚未打开,则在双击具有该扩展名的文件时它将打开.当然,该文件不会打开,因为我不编写任何代码来处理该事件,因为我不知道如何在OSX中检测到该事件已发生.

If MyApp is not yet open, it opens when double-clicking a file with that extension. Of course, the file does not open because I haven't written any code to handle the event because I don't know how to detect in OSX that the event has occurred.

如果MyApp已打开,我会收到一条消息无法打开文档"xxxx.myext".[MyApp]无法打开"[MyApp文件]"格式的文件.'

If MyApp is already open, I get, I get a message 'The document "xxxx.myext" could not be opened. [MyApp] cannot open files in the "[MyApp file]" format.'

所以我的问题是MyApp如何才能知道文件已被双击以启动文件打开过程?

So my question is how MyApp can know that a file has been double-clicked so that it can launch a file open procedure?

推荐答案

我最终回答了我自己的问题.三位作者分别给出了包含大部分必要代码的相当相似的单元.

I answered my own question eventually. Three authors had each given fairly similar units containing most of the necessary code.

克里斯·罗里斯顿(Chris Rolliston): https://delphihaven.wordpress.com/2012/08/14/associating-a-file-type-on-osx-part3/

Chris Rolliston: https://delphihaven.wordpress.com/2012/08/14/associating-a-file-type-on-osx-part3/

Victor Fedorenkov: https://pastebin.com/r4y6KmWz

Victor Fedorenkov: https://pastebin.com/r4y6KmWz

雷米·勒博(Remy Lebeau): https://forums.embarcadero.com/thread.jspa?messageID = 934522

Remy Lebeau: https://forums.embarcadero.com/thread.jspa?messageID=934522

这三个单元中的任何一个都不能在Delphi Tokyo 10.2中未经修改就使用,这无疑是由于自撰写文章以来Firemonkey进行了更改.

None of the three units could be used without modification in Delphi Tokyo 10.2, no doubt due to changes that have taken place in Firemonkey since the posts were written.

我分别使用了三个版本中的每个部分,并进行了各种编辑,以得到下面的单元,该单元可在Delphi 10.2 Update 3中使用:

I took parts of each of the three versions and made various edits to arrive at the unit below, which works in Delphi 10.2 Update 3:

unit NSApplicationOpenFileDelegateUnit.Mac;

interface

type

  TOpenFileEvent = reference to procedure(const AFileName: string);

procedure InstallApplicationDelegate2(const AOnOpenFile: TOpenFileEvent);

implementation

uses
  System.SysUtils, System.RTLConsts, System.Messaging, System.Classes,
  Macapi.ObjectiveC, Macapi.CoreFoundation, Macapi.CocoaTypes, Macapi.AppKit,
  Macapi.Foundation, FMX.Forms,
  Macapi.ObjCRuntime,
  FMX.Platform, FMX.Platform.Mac, FMX.Helpers.Mac;

type
  NSApplicationDelegate2 = interface(NSApplicationDelegate)
    ['{BE9AEDB7-80AC-49B1-8921-F226CC9310F4}']
    function application(theApplication: Pointer; openFile: CFStringRef)
      : Boolean; cdecl;
  end;

  TNSApplicationDelegate2 = class(TOCLocal, NSApplicationDelegate2)
  private
    FOnOpenFile: TOpenFileEvent;
  public
    constructor Create(const AOnOpenFile: TOpenFileEvent);
    procedure applicationDidFinishLaunching(Notification
      : NSNotification); cdecl;
    procedure applicationDidHide(Notification: NSNotification); cdecl;
    procedure applicationDidUnhide(Notification: NSNotification); cdecl;
    function applicationShouldTerminate(Notification: NSNotification)
      : NSInteger; cdecl;
    function applicationDockMenu(sender: NSApplication): NSMenu; cdecl;
    procedure applicationWillTerminate(Notification: NSNotification); cdecl;
    function application(theApplication: Pointer; openFile: CFStringRef)
      : Boolean; cdecl;
  end;

constructor TNSApplicationDelegate2.Create(const AOnOpenFile: TOpenFileEvent);
begin
  inherited Create;
  FOnOpenFile := AOnOpenFile;
end;

procedure TNSApplicationDelegate2.applicationDidFinishLaunching
  (Notification: NSNotification); cdecl;
begin
  // Seems we have to have this method even though it is empty.
end;

procedure TNSApplicationDelegate2.applicationDidHide(Notification
  : NSNotification); cdecl;
begin
  // Seems we have to have this method even though it is empty.
end;

procedure TNSApplicationDelegate2.applicationDidUnhide
  (Notification: NSNotification); cdecl;
begin
  // Seems we have to have this method even though it is empty.
end;

function TNSApplicationDelegate2.applicationShouldTerminate
  (Notification: NSNotification): NSInteger; cdecl;
begin
  Result := NSTerminateNow;
end;

function TNSApplicationDelegate2.applicationDockMenu(sender: NSApplication)
  : NSMenu; cdecl;
begin
  Result := nil;
end;

procedure TNSApplicationDelegate2.applicationWillTerminate
  (Notification: NSNotification); cdecl;
begin
  FreeAndNil(FMX.Forms.application);
end;

function TNSApplicationDelegate2.application(theApplication: Pointer;
  openFile: CFStringRef): Boolean; cdecl;
var
  Range: CFRange;
  S: String;
begin
  Result := Assigned(FOnOpenFile);
  if not Result then
    Exit;
  Range.location := 0;
  Range.length := CFStringGetLength(openFile);
  SetLength(S, Range.length);
  CFStringGetCharacters(openFile, Range, PChar(S));
  try
    FOnOpenFile(S);
  except
    on E: Exception do
    begin
      FMX.Forms.application.HandleException(E);
      Result := False;
    end;
  end;
end;

var
  Delegate: NSApplicationDelegate2;

procedure InstallApplicationDelegate2(const AOnOpenFile: TOpenFileEvent);
var
  NSApp: NSApplication;
begin
  NSApp := TNSApplication.Wrap(TNSApplication.OCClass.sharedApplication);
  Delegate := TNSApplicationDelegate2.Create(AOnOpenFile);
  NSApp.setDelegate(Delegate);
end;

end.

要使用该单位,请将此行包含在主窗体的FormCreate中:

To use the unit, include this line in the main form's FormCreate:

InstallApplicationDelegate2(OpenFile);

,还包括文件打开过程

procedure TMyMainForm.OpenFile(const AFileName: String);
begin
// Application-specific code to open the file
end;

现在在Finder中双击文件即可在应用程序中打开文件.

Double-clicking a file in Finder now opens the file up in the application.

以上假设您的应用程序和专有文件扩展名已经通过info.plist文件进行了关联.以下是一个info.plist,用于将文件扩展名".myext"与应用程序MyApp关联.

The above presupposes that your app and your proprietary file extension have already been associated via the info.plist file. The following is an info.plist to associate file extension ".myext" with an application MyApp.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleName</key>
    <string>My App Full Name</string>
    <key>CFBundleDisplayName</key>
    <string>My App Full Name</string>
    <key>CFBundleIdentifier</key>
    <string>com.mycompany.MyAppName</string>
    <key>CFBundleVersion</key>
    <string>1.0.6662</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleAllowMixedLocalizations</key>
    <string>YES</string>
    <key>CFBundleExecutable</key>
    <string>MyAppName</string>
    <key>NSHighResolutionCapable</key>
    <string>true</string>
    <key>LSApplicationCategoryType</key>
    <string>public.app-category.productivity</string>
    <key>NSLocationAlwaysUsageDescription</key>
    <string>The reason for accessing the location information of the 
    user</string>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>The reason for accessing the location information of the 
    user</string>
    <key>NSContactsUsageDescription</key>
    <string>The reason for accessing the contacts</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0.0</string>

    <key>CFBundleIconFile</key>
    <string>MyAppName.icns</string>
    <key>CFBundleSupportedPlatforms</key>
    <array>
        <string>MacOSX</string>
    </array>

<key>CFBundleDocumentTypes</key>
    <array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>com.mycompany.MyAppName.myext</string>
        </array>
        <key>LSHandlerRank</key>
        <string>Owner</string>
        <key>CFBundleTypeIconFile</key>
        <string>MyAppName.icns</string>
    </dict>
    </array>
    <key>UTExportedTypeDeclarations</key>
    <array>
    <dict>
        <key>UTTypeIdentifier</key>
        <string>com.mycompany.MyAppName.myext</string>
        <key>UTTypeTagSpecification</key>
        <dict>
            <key>public.filename-extension</key>
            <array>
                <string>myext</string>
            </array>
        </dict>
        <key>UTTypeConformsTo</key>
        <array>
            <string>public.data</string>
        </array>
        <key>UTTypeDescription</key>
        <string>My App Full Name document</string>
        <key>UTTypeIconFile</key>
        <string>MyAppName.icns</string>
    </dict>
    </array>
</dict>
</plist>

这篇关于将我的应用与其在OSX中的自定义文件类型相关联,然后双击打开文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆