Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos FireMonkey/Rad Studio XE2:如何在OS X上显示SaveDialog过滤器?_Macos_Delphi_Delphi Xe2_Firemonkey - Fatal编程技术网

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

Macos FireMonkey/Rad Studio XE2:如何在OS X上显示SaveDialog过滤器?,macos,delphi,delphi-xe2,firemonkey,Macos,Delphi,Delphi Xe2,Firemonkey,我创建了一个(Delphi XE2)Firemonkey示例程序,其中包含一个TButton和一个带有两个不同过滤器的TSavedialog。 (TSaveDialog组件支持Win32/Win64和OS X平台。) 它在Win32/Win64上运行良好,但我现在不知道为什么它在OS X(VirtualBox/OS X 10.7.X)上不显示Savedialog过滤器 如何让它在OSX上工作 procedure TForm1.Button_SaveClick(Sender: TObject);

我创建了一个(Delphi XE2)Firemonkey示例程序,其中包含一个TButton和一个带有两个不同过滤器的TSavedialog。 (TSaveDialog组件支持Win32/Win64和OS X平台。)

它在Win32/Win64上运行良好,但我现在不知道为什么它在OS X(VirtualBox/OS X 10.7.X)上不显示Savedialog过滤器

如何让它在OSX上工作

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;

保存对话框不是用Delphi构建的,而是调用本机MAC OSX对话框(NSSavePanel)。这没有用户可选择的过滤器

当您执行保存对话框时,Delphi将过滤器作为数组传递给NSSavePanel.SetAllowedFileTypes,它确定OSX对话框允许用户指定的扩展名,但没有可选列表

要允许用户从列表中进行选择,您需要创建自己的“文件类型选择”对话框,然后将该选择作为默认文件类型和唯一的筛选项传递给savedialog


创建一个全新的fileSave对话框并不容易,因为Firemonkey树组件似乎坚持扩展其所有节点,从而对硬盘上的所有文件执行完全遍历。在任何情况下,MAC用户都会熟悉标准对话框。

我在MAC OSX中遇到了与TopEndDialog相同的问题:过滤器不工作,但在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;
使用
Mac API基金会,MaCPAI ObjaveC,Macapi.AppKit;
{$IFDEF MACOS}
函数AllocFilterStr(常量S:string;变量Filter:NSArray):布尔;
变量
输入,模式:字符串;
文件类型:字符串数组;
结果,aux:TArray;
i、 j:整数;
FileTypesNS:指针数组;
NStr:NSString;
LocObj:ILocalObject;
开始
//首先,使用“|”作为分隔符拆分字符串
结果:=假;
输入:=S;
图案:='\\\';
结果:=TRegEx.Split(输入,模式);
图案:='\*\.';
SetLength(文件类型,0);
对于i:=0到长度(结果)-1 do
开始
如果是奇数(i)那么
如果结果[i]'*.*',则
如果AnsiLeftStr(结果[i],2)='*.',则
开始
aux:=TRegEx.Split(结果[i],模式);
对于j:=0到长度(辅助)-1 do
开始
aux[j]:=微调(aux[j]);
如果aux[j]'',则
开始
如果AnsiEndsStr(“;”,aux[j]),那么
aux[j]:=AnsiLeftStr(aux[j],长度(aux[j])-1;
SetLength(文件类型,长度(文件类型)+1);
FileTypes[length(FileTypes)-1]:=aux[j];
结束;
结束;
结束;
结束;
//从文件类型数组创建NSArray
SetLength(FileTypesNS,length(FileTypes));
对于i:=0到长度(文件类型)-1 do
开始
NStr:=NSSTR(文件类型[i]);
如果支持(NStr、ILocalObject、LocObj),则
FileTypesNS[i]:=LocObj.GetObjectID;
结束;
如果长度(文件类型)>0,则开始
筛选器:=TNSArray.Wrap(TNSArray.OCClass.arrayWithObjects(@FileTypesNS[0],length(FileTypes));
结果:=真;
结束;
结束;
函数CFToDelphiString(const CFStr:CFStringRef):string;
变量
范围:CFRange;
开始
Range.location:=0;
Range.length:=CFStringGetLength(CFStr);
设置长度(结果、范围、长度);
如果Range.length=0,则退出;
CFStringGetCharacters(CFStr、Range、PWideChar(结果));
结束;
函数NSToDelphiString(常量NSStr:NSString):字符串;内联;
开始
结果:=CFToDelphiString((NSStr作为ILocalObject).GetObjectID);
结束;
{$ENDIF}
程序TMainform.LoadClick(发件人:ToObject);
{$IFDEF MACOS}
变量
过滤器:NSArray;
LOpenDir:NSOpenPanel;
{$ENDIF}
开始
{$IFDEF MSWINDOWS}
Opendialog1.Filter:='*.fcb |*.fcb';
如果是Opendialog1.0,则执行
开始
案例Opendialog1.Filterindex的
1:LoadPlaylist(Opendialog1.filename,false,false);
2:LoadPlaylist(Opendialog1.filename,false,true);
结束;
结束;
{$ENDIF}
{$IFDEF MACOS}
LOpenDir:=TNSOpenPanel.Wrap(TNSOpenPanel.OCClass.openPanel);
如果AllocFilterStr('*.fcb |*.fcb',Filter),则
如果LOpenDir.runModalForTypes(Filter)=1,则
LoadPlaylist(nsodelphistring(LOpenDir.filename),false,false);
{$ENDIF}
结束;

David,谢谢你提供了非常有用的信息,但当我读到你的答案时,我不太高兴。我有一个MS Windows 3D文件格式(几何体)查看器/转换器(),支持615种不同的文件格式(292用于保存!),我正在FireMonkey下移植此程序,以获取Win32/Win64和OS X可执行文件。我想我将使用一个简单的组合框来选择格式(第二个组合框用于从最喜欢的格式中选择),另一个组合框用于选择文件名。