I have a need for a user to be able to select an existing read-only file from a save dialog. I thought you could do this with a judicious selection of the TSaveDialog
options but I can't make it happen. If I select a R/O file, as soon as I hit the Save
button I get the message:
Read-only.txt
This file is set to read-only.
Try again with a different file name.
I imagined the option bit ofNoReadOnlyReturn
would control this, but it seems to have no effect.
What am I missing?
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
The issue is not with
TSaveDialog
itself, but with the underlying Win32GetSaveFileName()
/IFileSaveDialog
APIs thatTSaveDialog
uses internally. They simply do not allow a read/only file to be the result of a "save" dialog.That being said,
IFileSaveDialog
does provide a possible (albeit ugly) workaround. If you enable the dialog'sFOS_OVERWRITEPROMPT
flag, then selecting an existing file will prompt the user if the file can be overwritten before closing the dialog. TheIFileDialogEvents
interface has anOnOverwrite
event, which is fired before that prompt appears (and can returnFDESVR_ACCEPT
to skip the prompt completely). So, in that event, you could remove the file'sFILE_ATTRIBUTE_READONLY
attribute before the dialog is closed. However, the dialog will still display the same "This file is set to read-only" error message and refuse to close (presumably because it has checked the attribute before firing theOnOverwrite
event), but if you then select the same file again, the attribute will have been cleared and the dialog will accept the file (that is the ugly part - you would have to train your managers to ignore that error and retry).GetSaveFileName()
has anofOverwritePrompt
flag, but no event for overwrite prompting.That being said,
TSaveDialog
does not expose access to theIFileSaveDialog.OnOverwrite
event when it usesIFileSaveDialog
internally, but you can useTFileSaveDialog
instead, which does.