Delphi 2007 - 允许在 TSaveDialog 中选择只读文件

Delphi 2007 - Allowing a Read-only file to be selected in a TSaveDialog

我需要用户能够从保存对话框中 select 现有的只读文件。我认为您可以使用明智的 selection TSaveDialog 选项来做到这一点,但我无法做到这一点。如果我 select 一个 R/O 文件,只要我点击 Save 按钮,我就会收到消息:

    Read-only.txt
    This file is set to read-only.
    Try again with a different file name.

我以为选项位ofNoReadOnlyReturn会控制这个,但似乎没有效果。

我错过了什么?

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

-

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    SaveDialog1: TSaveDialog;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
if SaveDialog1.Execute then
    begin
    Windows.Beep (1000, 300) ;
    end ;
end ;

end.

-

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 69
  ClientWidth = 195
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 56
    Top = 18
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
  object SaveDialog1: TSaveDialog
    FileName = 'Read-only.txt'
    InitialDir = 'C:\Users\Ross\Documents\RAD Studio\Projects'
    Options = [ofHideReadOnly, ofNoReadOnlyReturn, ofEnableSizing]
    Left = 16
    Top = 16
  end
end

问题不在于 TSaveDialog 本身,而在于 TSaveDialog 内部使用的底层 Win32 GetSaveFileName()/IFileSaveDialog API。他们根本不允许 read/only 文件是 "save" 对话框的结果。

话虽这么说,IFileSaveDialog 确实提供了 可能的 (尽管丑陋)解决方法。如果启用对话框的 FOS_OVERWRITEPROMPT 标志,则 selecting 现有文件将提示用户是否可以在关闭对话框之前覆盖该文件。 IFileDialogEvents 界面有一个 OnOverwrite 事件,该事件在该提示出现之前触发(并且可以 return FDESVR_ACCEPT 完全跳过提示)。因此,在那种情况下,您可以在关闭对话框之前删除文件的 FILE_ATTRIBUTE_READONLY 属性。但是,该对话框仍将显示相同的 "This file is set to read-only" 错误消息并拒绝关闭(可能是因为它在触发 OnOverwrite 事件之前已经检查了属性),但是如果您随后 select 相同再次文件,该属性将被清除并且对话框将接受该文件(这是丑陋的部分 - 你必须训练你的经理忽略该错误并重试)。

GetSaveFileName()有一个ofOverwritePrompt标志,但没有覆盖提示的事件。

也就是说,TSaveDialog 在内部使用 IFileSaveDialog 时不会公开对 IFileSaveDialog.OnOverwrite 事件的访问权限,但您可以改用 TFileSaveDialog,而确实如此。