Delphi (保存对话框)如何在Vista/Win7中更改文件过滤器时自动更改文件扩展名?
在显示保存对话框时,我想自动钩住用户的过滤器类型更改和更改文件扩展名。(例如,与MSPaint的“另存为”操作类似。) 使用TSaveDialog并设置UseLatestCommonDialogs:=False, 我可以通过下面的代码来处理这个问题。(当然,没有最新的通用对话框支持。) 我想用Delphi2007同时支持XP和vista/7 我应该使用TFileSaveDialog而不是带有内部包装的TSaveDialog吗? (而且我必须努力使用COM编程?) 或者我可以通过TFileSaveDialog和它的标准属性来实现这一点吗? (我的开发环境仍然在XP机器上,所以我从未尝试过。对不起。)Delphi (保存对话框)如何在Vista/Win7中更改文件过滤器时自动更改文件扩展名?,delphi,windows-7,windows-vista,savefiledialog,save-as,Delphi,Windows 7,Windows Vista,Savefiledialog,Save As,在显示保存对话框时,我想自动钩住用户的过滤器类型更改和更改文件扩展名。(例如,与MSPaint的“另存为”操作类似。) 使用TSaveDialog并设置UseLatestCommonDialogs:=False, 我可以通过下面的代码来处理这个问题。(当然,没有最新的通用对话框支持。) 我想用Delphi2007同时支持XP和vista/7 我应该使用TFileSaveDialog而不是带有内部包装的TSaveDialog吗? (而且我必须努力使用COM编程?) 或者我可以通过TFileSave
我认为这是一项非常常见的任务,但我找不到任何支持Vista/7的示例代码…据我所知,TFileSaveDialog将在XP上引发异常。它需要Vista或更高版本 更新:从事件处理程序改编的TFileSaveDialog的一些D2010代码。
(我在Vista上没有D2007;请使用PWideChar而不是PChar) 文件保存对话框的位置为:
object FileSaveDialog1: TFileSaveDialog
FavoriteLinks = <>
FileTypes = <
item
DisplayName = 'png files'
FileMask = '*.png'
end
item
DisplayName = 'bmp files'
FileMask = '*.bmp'
end
item
DisplayName = 'jpg files'
FileMask = '*.jpg'
end>
Options = []
OnTypeChange = FileSaveDialog1TypeChange
end
对象文件保存对话框1:TFileSaveDialog
收藏夹链接=
文件类型=<
项目
DisplayName='png文件'
文件掩码=“*.png”
结束
项目
DisplayName='bmp文件'
文件掩码=“*.bmp”
结束
项目
DisplayName='jpg文件'
FileMask='*.jpg'
结束>
选项=[]
OnTypeChange=FileSaveDialog1TypeChange
结束
您写道无法破解包装器。我在XLSX/XLS/ODS导出库中使用此代码来更改XP和Vista+上的文件扩展名
一个缺点是:类助手无法访问Delphi2007中的私有字段,因此此代码仅适用于Delphi2009+。如果希望与Delphi 2007兼容,请使用与本例中TFileDialogWrapper相同的TOpenDialog方法
{ interface }
//some hacking needed to change the file extension at type change,
//empty class is just fine...
TFileDialogWrapper = class(TObject)
private
{$HINTS OFF}
procedure AssignFileTypes;
procedure AssignOptions;
function GetFileName: TFileName;
function GetHandle: HWND;
procedure HandleShareViolation(Sender: TObject;
var Response: TFileDialogShareViolationResponse);
procedure OnFileOkEvent(Sender: TObject; var CanClose: Boolean);
procedure OnFolderChangeEvent(Sender: TObject);
procedure OnSelectionChangeEvent(Sender: TObject);
procedure OnTypeChangeEvent(Sender: TObject);
protected
FFileDialog: TCustomFileDialog;
{$HINTS ON}
end;
TOpenDialogHelper = class helper for TOpenDialog
public
function GetInternalWrapper: TFileDialogWrapper;
end;
{ implementation }
{ TOpenDialogHelper }
function TOpenDialogHelper.GetInternalWrapper: TFileDialogWrapper;
begin
Result := TFileDialogWrapper(Self.FInternalWrapper);
end;
{ TFileDialogWrapper }
procedure TFileDialogWrapper.AssignFileTypes;
begin
end;
procedure TFileDialogWrapper.AssignOptions;
begin
end;
function TFileDialogWrapper.GetFileName: TFileName;
begin
end;
function TFileDialogWrapper.GetHandle: HWND;
begin
end;
procedure TFileDialogWrapper.HandleShareViolation(Sender: TObject;
var Response: TFileDialogShareViolationResponse);
begin
end;
procedure TFileDialogWrapper.OnFileOkEvent(Sender: TObject;
var CanClose: Boolean);
begin
end;
procedure TFileDialogWrapper.OnFolderChangeEvent(Sender: TObject);
begin
end;
procedure TFileDialogWrapper.OnSelectionChangeEvent(Sender: TObject);
begin
end;
procedure TFileDialogWrapper.OnTypeChangeEvent(Sender: TObject);
begin
end;
//use this for OnTypeChane event of a "normal" TOpenDialog / TSaveDialog
procedure TForm1.DialogTypeChange(Sender: TObject);
var
xFN: WideString;
xExporter: TOCustomExporter;
xFileName: PWideChar;
xFD: TFileDialogWrapper;
xFilterIndex: UINT;
begin
if Sender is TOpenDialog then
with TOpenDialog(Sender) do begin
xFD := GetInternalWrapper;
if (xFD <> nil) and (xFD.FFileDialog <> nil)
then begin
//Vista file dialog
xFD.FFileDialog.Dialog.GetFileName(xFileName);
if xFileName = '' then
exit;
xFN := xFileName;
xFD.FFileDialog.Dialog.GetFileTypeIndex(xFilterIndex);
// DO WHATEVER YOU WANT WITH THE FILENAME HERE //
xFD.FFileDialog.Dialog.SetFileName(PWideChar(xFN));
end else begin
//Old dialog
xFN := ExtractFileName(FileName);
if xFN = '' then
exit;
// DO WHATEVER YOU WANT WITH THE FILENAME HERE //
{$HINTS OFF}
SendMessage(Windows.GetParent(Handle), CDM_SETCONTROLTEXT, 1152, LongInt(PWideChar(xFN)));
{$HINTS ON}
end;
end;
end;
{interface}
//一些黑客需要在类型更改时更改文件扩展名,
//空课很好。。。
TFileDialogWrapper=类(ToObject)
私有的
{$OFF}
程序文件类型;
程序选择;
函数GetFileName:TFileName;
函数GetHandle:HWND;
程序句柄共享(发送方:ToObject;
var响应:TFileDialogShareViolationResponse);
过程onFileOkeEvent(发送方:TObject;变量CanClose:Boolean);
FolderChangeEvent的过程(发送方:ToObject);
选择变更事件的程序(发送方:ToObject);
类型更改事件的过程(发送方:ToObject);
受保护的
FFileDialog:TCustomFileDialog;
{$HINTS ON}
结束;
TopEndDialogHelper=TopEndDialog的类帮助器
公众的
函数GetInternalWrapper:TFileDialogWrapper;
结束;
{实现}
{TOpenDialogHelper}
函数TOpenDialogHelper.GetInternalWrapper:TFileDialogWrapper;
开始
结果:=TFileDialogWrapper(Self.FInternalWrapper);
结束;
{TFileDialogWrapper}
过程TFileDialogWrapper.AssignFileTypes;
开始
结束;
程序TFileDialogWrapper.AssignOptions;
开始
结束;
函数TFileDialogWrapper.GetFileName:TFileName;
开始
结束;
函数TFileDialogWrapper.GetHandle:HWND;
开始
结束;
过程TFileDialogWrapper.HandleShareVersion(发送方:ToObject;
var响应:TFileDialogShareViolationResponse);
开始
结束;
过程TFileDialogWrapper.onFileOkeEvent(发送方:ToObject;
变量CanClose:布尔值);
开始
结束;
过程TFileDialogWrapper.OnFolderChangeEvent(发送方:ToObject);
开始
结束;
过程TFileDialogWrapper.OnSelectionChangeEvent(发送方:ToObject);
开始
结束;
过程TFileDialogWrapper.OnTypeChangeEvent(发送方:ToObject);
开始
结束;
//用于“正常”TopEndDialog/TSaveDialog的OnTypeChane事件
程序TForm1.DialogTypeChange(发送方:ToObject);
变量
xFN:宽字符串;
xExporter:TOCustomExporter;
xFileName:PWideChar;
xFD:TFileDialogWrapper;
xFilterIndex:UINT;
开始
如果发送方是TopEndDialog,则
使用TopEndDialog(发送方)开始
xFD:=GetInternalWrapper;
if(xFD nil)和(xFD.FFileDialog nil)
然后开始
//Vista文件对话框
xFD.FFileDialog.Dialog.GetFileName(xFileName);
如果xFileName='',则
出口
xFN:=xFileName;
xFD.FFileDialog.Dialog.GetFileTypeIndex(xFilterIndex);
//使用此处的文件名执行任何操作//
SetFileName(PWideChar(xFN));
结束,否则开始
//旧对话
xFN:=提取文件名(文件名);
如果xFN='',则
出口
//使用此处的文件名执行任何操作//
{$OFF}
SendMessage(Windows.GetParent(Handle),CDM_SETCONTROLTEXT,1152,LongInt(PWideChar(xFN));
{$HINTS ON}
结束;
结束;
结束;
编辑:实际上,如果您设置了
DefaultExt
属性,Delphi/Windows会为您更改文件扩展名。在这种情况下,您不必在OnTypeChange
事件中执行任何操作。此功能在Delphi中实现,但默认情况下禁用
要激活它,只需在
DefaultExt
属性中输入默认扩展名。谢谢!但我通常在运行时创建这些对话框,这样我就可以通过OS版本检查切换TSaveDialog和TFileSaveDialog。它可以与D2007一起使用。我只是更改了PChar/string->PWideChar/WideString(可能在D2009或更高版本上使用自动类型转换)。谢谢p、 我尝试在“*SaveDialog1*TypeChange”中切换,使用类似“if Parent.ClassName='TFileSaveDialogWrapper'”(这比切换对话框类更方便。)但我无法破解wrapper,因为它 是在实现部分定义的…实际上,我现在检查了它-它只在Delphi XE+中工作,因为对话框单元架构。谢谢您的回答。我刚注意到。我不再使用D2007了,我会读你的代码。谢谢
object FileSaveDialog1: TFileSaveDialog
FavoriteLinks = <>
FileTypes = <
item
DisplayName = 'png files'
FileMask = '*.png'
end
item
DisplayName = 'bmp files'
FileMask = '*.bmp'
end
item
DisplayName = 'jpg files'
FileMask = '*.jpg'
end>
Options = []
OnTypeChange = FileSaveDialog1TypeChange
end
{ interface }
//some hacking needed to change the file extension at type change,
//empty class is just fine...
TFileDialogWrapper = class(TObject)
private
{$HINTS OFF}
procedure AssignFileTypes;
procedure AssignOptions;
function GetFileName: TFileName;
function GetHandle: HWND;
procedure HandleShareViolation(Sender: TObject;
var Response: TFileDialogShareViolationResponse);
procedure OnFileOkEvent(Sender: TObject; var CanClose: Boolean);
procedure OnFolderChangeEvent(Sender: TObject);
procedure OnSelectionChangeEvent(Sender: TObject);
procedure OnTypeChangeEvent(Sender: TObject);
protected
FFileDialog: TCustomFileDialog;
{$HINTS ON}
end;
TOpenDialogHelper = class helper for TOpenDialog
public
function GetInternalWrapper: TFileDialogWrapper;
end;
{ implementation }
{ TOpenDialogHelper }
function TOpenDialogHelper.GetInternalWrapper: TFileDialogWrapper;
begin
Result := TFileDialogWrapper(Self.FInternalWrapper);
end;
{ TFileDialogWrapper }
procedure TFileDialogWrapper.AssignFileTypes;
begin
end;
procedure TFileDialogWrapper.AssignOptions;
begin
end;
function TFileDialogWrapper.GetFileName: TFileName;
begin
end;
function TFileDialogWrapper.GetHandle: HWND;
begin
end;
procedure TFileDialogWrapper.HandleShareViolation(Sender: TObject;
var Response: TFileDialogShareViolationResponse);
begin
end;
procedure TFileDialogWrapper.OnFileOkEvent(Sender: TObject;
var CanClose: Boolean);
begin
end;
procedure TFileDialogWrapper.OnFolderChangeEvent(Sender: TObject);
begin
end;
procedure TFileDialogWrapper.OnSelectionChangeEvent(Sender: TObject);
begin
end;
procedure TFileDialogWrapper.OnTypeChangeEvent(Sender: TObject);
begin
end;
//use this for OnTypeChane event of a "normal" TOpenDialog / TSaveDialog
procedure TForm1.DialogTypeChange(Sender: TObject);
var
xFN: WideString;
xExporter: TOCustomExporter;
xFileName: PWideChar;
xFD: TFileDialogWrapper;
xFilterIndex: UINT;
begin
if Sender is TOpenDialog then
with TOpenDialog(Sender) do begin
xFD := GetInternalWrapper;
if (xFD <> nil) and (xFD.FFileDialog <> nil)
then begin
//Vista file dialog
xFD.FFileDialog.Dialog.GetFileName(xFileName);
if xFileName = '' then
exit;
xFN := xFileName;
xFD.FFileDialog.Dialog.GetFileTypeIndex(xFilterIndex);
// DO WHATEVER YOU WANT WITH THE FILENAME HERE //
xFD.FFileDialog.Dialog.SetFileName(PWideChar(xFN));
end else begin
//Old dialog
xFN := ExtractFileName(FileName);
if xFN = '' then
exit;
// DO WHATEVER YOU WANT WITH THE FILENAME HERE //
{$HINTS OFF}
SendMessage(Windows.GetParent(Handle), CDM_SETCONTROLTEXT, 1152, LongInt(PWideChar(xFN)));
{$HINTS ON}
end;
end;
end;