You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现双击文件在FireMonkey运行实例中打开(Win32/OSX)

实现FireMonkey单实例打开关联文件(Win32 + OSX)

Win32平台实现

1. 完善单实例检测与文件路径传递

你已经用互斥量实现了单实例阻止,现在需要让第二个启动的实例把双击的文件路径传递给已运行的实例。这里推荐用WM_COPYDATA消息,它比自定义消息更安全,适合传递字符串类数据:

修改你的.dpr文件代码如下:

program MyFMXApp;

uses
  Vcl.Forms,
  System.SysUtils,
  Winapi.Windows,
  MainForm in 'MainForm.pas' {Form1};

const
  MUTEX_NAME = 'MyUniqueFMXAppMutex'; // 务必确保这个名称唯一,避免和其他应用冲突

var
  OneInstanceMutex: THandle;
  MainWnd: HWND;
  CopyData: TCopyDataStruct;
begin
  OneInstanceMutex := CreateMutex(nil, True, PChar(MUTEX_NAME));
  if (GetLastError = ERROR_ALREADY_EXISTS) then
  begin
    // 查找第一个实例的主窗口(这里用应用标题定位,也可以用窗口类名更可靠)
    MainWnd := FindWindow(nil, PChar(Application.Title));
    if MainWnd <> 0 then
    begin
      // 准备传递的文件路径(ParamStr(1)是系统传入的双击文件路径)
      CopyData.dwData := 0;
      CopyData.cbData := (Length(ParamStr(1)) + 1) * SizeOf(Char);
      CopyData.lpData := PChar(ParamStr(1));
      // 发送消息传递路径
      SendMessage(MainWnd, WM_COPYDATA, 0, LPARAM(@CopyData));
      // 把已运行实例窗口激活到前台
      SetForegroundWindow(MainWnd);
    end;
    Exit;
  end;

  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;

  ReleaseMutex(OneInstanceMutex);
  CloseHandle(OneInstanceMutex);
end.

2. 在主窗体中接收并处理文件

在主窗体代码里添加WM_COPYDATA的消息处理逻辑:

unit MainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, FMX.Types,
  FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs;

type
  TForm1 = class(TForm)
  private
    procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;
    procedure OpenFile(const FilePath: string); // 你的自定义文件打开逻辑
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.WMCopyData(var Msg: TWMCopyData);
var
  FilePath: string;
begin
  inherited;
  if Msg.CopyDataStruct.dwData = 0 then
  begin
    // 解析传递过来的文件路径
    FilePath := PChar(Msg.CopyDataStruct.lpData);
    // 调用自定义逻辑打开文件
    OpenFile(FilePath);
  end;
  Msg.Result := 1; // 告知发送方已成功接收
end;

procedure TForm1.OpenFile(const FilePath: string);
begin
  // 这里写你的文件加载逻辑,比如读取文件内容到控件
  ShowMessage('已打开文件:' + FilePath);
end;

end.

OSX平台实现

OSX的逻辑和Win32差异较大,依赖Apple的Launch Services机制,会自动将文件路径传递给已运行的应用实例:

1. 自定义Application Delegate处理文件打开

在主窗体或.dpr中添加OSX条件编译的代码:

{$IFDEF MACOS}
uses
  Macapi.AppKit, Macapi.Foundation, FMX.Platform.Mac;

type
  TCustomAppDelegate = class(TOSXApplicationDelegate)
  public
    function applicationOpenFile(Application: NSApplication; filename: NSString): Boolean; override;
  end;

function TCustomAppDelegate.applicationOpenFile(Application: NSApplication; filename: NSString): Boolean;
var
  FilePath: string;
begin
  Result := inherited;
  // 将NSString转换为Delphi字符串
  FilePath := UTF8ToString(filename.UTF8String);
  // 调用主窗体的打开方法
  if Assigned(Form1) then
  begin
    Form1.OpenFile(FilePath);
    // 激活应用到前台
    Application.activateIgnoringOtherApps(True);
  end;
end;
{$ENDIF}

然后在.dpr的Application.Initialize之前设置自定义Delegate:

{$IFDEF MACOS}
var
  CustomDelegate: TCustomAppDelegate;
begin
  CustomDelegate := TCustomAppDelegate.Create;
  TOSXApplicationDelegate.SetApplicationDelegate(CustomDelegate);
{$ENDIF}

2. 设置文件关联(修改Info.plist)

需要在应用的Info.plist中添加文件类型关联,让OSX识别你的文件扩展名并绑定到应用。添加以下XML内容(替换成你的文件类型信息):

<key>CFBundleDocumentTypes</key>
<array>
  <dict>
    <key>CFBundleTypeName</key>
    <string>我的自定义文件</string>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>LSHandlerRank</key>
    <string>Owner</string>
    <key>LSItemContentTypes</key>
    <array>
      <string>com.yourcompany.yourappfile</string>
    </array>
  </dict>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
  <dict>
    <key>UTTypeIdentifier</key>
    <string>com.yourcompany.yourappfile</string>
    <key>UTTypeDescription</key>
    <string>我的自定义文件格式</string>
    <key>UTTypeConformsTo</key>
    <array>
      <string>public.data</string>
    </array>
    <key>UTTypeTagSpecification</key>
    <dict>
      <key>public.filename-extension</key>
      <array>
        <string>myext</string> <!-- 替换成你的文件扩展名 -->
      </array>
    </dict>
  </dict>
</array>

额外注意事项

  • Win32下如果应用标题可能动态变化,建议用窗口类名定位主窗口(可以通过Spy++查看FMX主窗口的类名,一般对应你的窗体类名,比如TForm1)。
  • OSX测试文件关联时,建议将应用安装到Applications目录,否则Launch Services可能无法正确识别关联关系。
  • 两个平台的OpenFile方法可以统一实现,利用FMX的跨平台API处理文件读取,减少重复代码。

内容的提问来源于stack exchange,提问作者Duns

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:51:34