简体   繁体   English

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

[英]FireMonkey/Rad Studio XE2: How can I show the SaveDialog filter on OS X?

I created an (Delphi XE2) Firemonkey sample program which contains a TButton and a TSavedialog with two different filters. 我创建了一个(Delphi XE2)Firemonkey示例程序,其中包含一个TButton和一个带有两个不同过滤器的TSavedialog。 (The TSaveDialog component supports the Win32/Win64 and OS X platform.) (TSaveDialog组件支持Win32 / Win64和OS X平台。)

It works fine on Win32/Win64, but I don't now why it does not show the Savedialog filters on OS X (VirtualBox/OS X 10.7.x). 它在Win32 / Win64上可以正常工作,但是我现在不为什么在OS X(VirtualBox / OS X 10.7.x)上不显示Savedialog过滤器。

How can I get it to work on OS X ? 如何在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;

The Save dialog is not constructed in Delphi but calls the native MAC OSX dialog (NSSavePanel). “保存”对话框不是在Delphi中构建的,而是调用本机MAC OSX对话框(NSSavePanel)。 This does not have a user selectable filter. 它没有用户可选的过滤器。

When you execute a save dialog, Delphi passes the filter as an array to NSSavePanel.SetAllowedFileTypes which determines what extensions the OSX dialog will allow the user to specify - but there is no selectable list. 当执行一个保存对话框时,Delphi将过滤器作为数组传递给NSSavePanel.SetAllowedFileTypes,它确定OSX对话框将允许用户指定哪些扩展名-但没有可选列表。

To allow the user to select from a list, you would need to create your own filetype selection dialog box and then take that selection and pass to the savedialog as the default file type and the only filter item. 要允许用户从列表中进行选择,您需要创建自己的文件类型选择对话框,然后进行选择并将其作为默认文件类型和唯一过滤器项传递给saveialog。

The alternative of creating a completely new fileSave dialog is not easy as the Firemonkey tree component seems to insist on expanding all its nodes and hence performs a complete traverse of all the files on your hard drive. 创建全新的fileSave对话框的方法并不容易,因为Firemonkey树组件似乎坚持要扩展其所有节点,因此要对硬盘上的所有文件进行完整遍历。 In any case, MAC users will be familiar with the standard dialog. 无论如何,MAC用户都会熟悉标准对话框。

I had got the same problem with TOpendialog in MAC OSX: filter don't work, but in Windows they do. 我在MAC OSX中使用TOpendialog遇到了同样的问题:过滤器不起作用,但是在Windows中却可以。 Now I solved the problem, perhaps you can use the code for your workaround. 现在,我解决了这个问题,也许您可​​以将代码用于解决方法。 Those files which are NOT displayed in Windows are disabled under MAC OSX, you cannot select them. Windows OS中未显示的那些文件在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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM