我创建了一个(Delphi XE2)Firemonkey示例程序,其中包含一个TButton和一个带有两个不同过滤器的TSavedialog。 (TSaveDialog组件支持Win32 / Win64和OS X平台。)
它在Win32 / Win64上工作正常,但我现在不知道为什么它不显示OS X上的Savedialog过滤器(VirtualBox / OS X 10.7.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;
答案 0 :(得分:3)
“保存”对话框不是在Delphi中构建的,而是调用本机MAC OSX对话框(NSSavePanel)。这没有用户可选择的过滤器。
当您执行保存对话框时,Delphi将过滤器作为数组传递给NSSavePanel.SetAllowedFileTypes,它确定OSX对话框允许用户指定的扩展名 - 但是没有可选列表。
要允许用户从列表中进行选择,您需要创建自己的文件类型选择对话框,然后选择该选项并将其作为默认文件类型和唯一的过滤项目传递给savedialog。
创建一个全新的fileSave对话框的替代方法并不容易,因为Firemonkey树组件似乎坚持扩展其所有节点,因此执行硬盘驱动器上所有文件的完整遍历。在任何情况下,MAC用户都会熟悉标准对话框。
答案 1 :(得分:1)
我在MAC OSX中遇到了与TOpendialog相同的问题:过滤器不起作用,但在Windows中它们可以。现在我解决了这个问题,也许你可以使用代码来解决问题。在MAC OSX下禁用那些未在Windows中显示的文件,您无法选择它们。
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;