Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.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
Delphi (保存对话框)如何在Vista/Win7中更改文件过滤器时自动更改文件扩展名?_Delphi_Windows 7_Windows Vista_Savefiledialog_Save As - Fatal编程技术网

Delphi (保存对话框)如何在Vista/Win7中更改文件过滤器时自动更改文件扩展名?

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

在显示保存对话框时,我想自动钩住用户的过滤器类型更改和更改文件扩展名。(例如,与MSPaint的“另存为”操作类似。)

使用TSaveDialog并设置UseLatestCommonDialogs:=False, 我可以通过下面的代码来处理这个问题。(当然,没有最新的通用对话框支持。)

我想用Delphi2007同时支持XP和vista/7

我应该使用TFileSaveDialog而不是带有内部包装的TSaveDialog吗? (而且我必须努力使用COM编程?)

或者我可以通过TFileSaveDialog和它的标准属性来实现这一点吗? (我的开发环境仍然在XP机器上,所以我从未尝试过。对不起。)


我认为这是一项非常常见的任务,但我找不到任何支持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;