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

后端 未结 2 1480
有刺的猬
有刺的猬 2021-01-12 07:29

I created an (Delphi XE2) Firemonkey sample program which contains a TButton and a TSavedialog with two different filters. (The TSaveDialog component supports the Win32/Win6

2条回答
  •  有刺的猬
    2021-01-12 08:19

    I had got the same problem with TOpendialog in MAC OSX: filter don't work, but in Windows they do. 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.

    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;
        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;
    

提交回复
热议问题