FireMonkey/Rad Studio XE2:如何在OS X上显示SaveDialog过滤器?

8
我创建了一个(Delphi XE2)Firemonkey示例程序,其中包含一个TButton和一个TSavedialog,具有两个不同的过滤器。 (TSaveDialog组件支持Win32 / Win64和OS X平台。) 在Win32 / Win64上运行正常,但我不知道为什么在OS X(VirtualBox / OS X 10.7.x)上不显示Savedialog过滤器。 如何使其在OS X上运行?
procedure TForm1.Button_SaveClick(Sender: TObject);
begin
  SaveDialog.Filter:='Format_1 (*.fmt1)|*.fmt1|Format_2 (*.fmt2)|*.fmt2';

  If Savedialog.Execute Then ShowMessage(SaveDialog.FileName+#13+'Selected filterindex: '+Inttostr(SaveDialog.FilterIndex));
end;
2个回答

3
保存对话框并非由Delphi构建,而是调用本机MAC OSX对话框(NSSavePanel)。这种对话框没有可选的过滤器。当你执行保存对话框时,Delphi将过滤器作为数组传递给NSSavePanel.SetAllowedFileTypes,该方法确定OSX对话框允许用户指定什么扩展名-但没有可选列表。要允许用户从列表中选择,您需要创建自己的文件类型选择对话框,然后将该选择作为默认文件类型和唯一的过滤器项目传递给保存对话框。创建完全新的文件保存对话框的替代方法并不容易,因为Firemonkey树组件似乎坚持展开其所有节点,因此会对硬盘上的所有文件进行完整遍历。无论如何,MAC用户将熟悉标准对话框。

David,感谢您提供非常有用的信息,但当我看到您的回答时,我并不是太开心。 - Zoltan Karpati
我有一个MS Windows 3D文件格式(几何)查看器/转换器(http://web.t-online.hu/karpo),支持615种不同的文件格式(其中292个用于保存!),我正在将此程序移植到FireMonkey下以获取Win32 / Win64和OS X可执行文件。我认为我将使用一个简单的ComboBox来选择格式(并使用第二个ComboBox来选择喜爱的格式),并使用SaveDialog来选择文件名。 - Zoltan Karpati

1
我在MAC OSX中遇到了与TOpendialog相同的问题:筛选器不起作用,但在Windows中它们可以。现在我解决了这个问题,也许你可以使用代码来解决。在Windows中未显示的文件在MAC OSX下被禁用,无法选择它们。
uses
  Macapi.Foundation, Macapi.ObjectiveC, Macapi.AppKit;


 {$IFDEF MACOS}

  function AllocFilterStr(const S: string; var Filter: NSArray): Boolean;
  var
    input, pattern: string;
    FileTypes: array of string;
    outcome, aux: TArray<string>;
    i, j: Integer;
    FileTypesNS: array of Pointer;
    NStr: NSString;
    LocObj: ILocalObject;
  begin
    // First, split the string by using '|' as a separator
    Result := false;
    input := S;
    pattern := '\|';

    outcome := TRegEx.Split(input, pattern);
    pattern := '\*\.';
    SetLength(FileTypes, 0);

    for i := 0 to length(outcome) - 1 do
    begin
      if Odd(i) then
        if outcome[i] <> '*.*' then
          if AnsiLeftStr(outcome[i], 2) = '*.' then
          begin
            aux := TRegEx.Split(outcome[i], pattern);
            for j := 0 to length(aux) - 1 do
            begin
              aux[j] := Trim(aux[j]);
              if aux[j] <> '' then
              begin
                if AnsiEndsStr(';', aux[j]) then
                  aux[j] := AnsiLeftStr(aux[j], length(aux[j]) - 1);
                SetLength(FileTypes, length(FileTypes) + 1);
                FileTypes[length(FileTypes) - 1] := aux[j];
              end;
            end;
          end;
    end;

    // create the NSArray from the FileTypes array
    SetLength(FileTypesNS, length(FileTypes));
    for i := 0 to length(FileTypes) - 1 do
    begin
      NStr := NSSTR(FileTypes[i]);
      if Supports(NStr, ILocalObject, LocObj) then
        FileTypesNS[i] := LocObj.GetObjectID;
    end;
    if length(FileTypes) > 0 then begin
      Filter := TNSArray.Wrap(TNSArray.OCClass.arrayWithObjects(@FileTypesNS[0], length(FileTypes)));
      result := true;
    end;
  end;

function CFToDelphiString(const CFStr: CFStringRef): string;
var
  Range: CFRange;
begin
  Range.location := 0;
  Range.length := CFStringGetLength(CFStr);
  SetLength(Result, Range.length);
  if Range.length = 0 then Exit;
  CFStringGetCharacters(CFStr, Range, PWideChar(Result));
end;

function NSToDelphiString(const NSStr: NSString): string; inline;
begin
  Result := CFToDelphiString((NSStr as ILocalObject).GetObjectID);
end;


  {$ENDIF}


procedure TMainform.LoadClick(Sender: TObject);
 {$IFDEF MACOS}
var
  Filter: NSArray;
  LOpenDir: NSOpenPanel;
  {$ENDIF}
begin

  {$IFDEF MSWINDOWS}
  Opendialog1.Filter:= '*.fcb|*.fcb';
  if Opendialog1.execute then
  begin
    case Opendialog1.Filterindex of
      1:  LoadPlaylist(Opendialog1.filename, false, false);
      2:  LoadPlaylist(Opendialog1.filename, false, true);
    end;
  end;
  {$ENDIF}

 {$IFDEF MACOS}
  LOpenDir := TNSOpenPanel.Wrap(TNSOpenPanel.OCClass.openPanel);
  if AllocFilterStr('*.fcb|*.fcb', Filter) then
  if LOpenDir.runModalForTypes(Filter)=1 then
    LoadPlaylist(NSToDelphiString(LOpenDir.filename), false, false);
  {$ENDIF}
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接