|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
//
// Description:
// SaveFileDialog is a sealed class derived from FileDialog that
// implements File Save dialog-specific functions. It contains
// additional properties relevant only to save dialogs.
//
//
namespace Microsoft.Win32
{
using MS.Internal.AppModel;
using MS.Internal.Interop;
using MS.Internal.PresentationFramework;
using MS.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Windows;
/// <summary>
/// Represents a common dialog box that allows the user to specify options
/// for saving a file. This class cannot be inherited.
/// </summary>
public sealed class SaveFileDialog : FileDialog
{
//---------------------------------------------------
//
// Constructors
//
//---------------------------------------------------
#region Constructors
// We add a constructor for our SaveFileDialog since we have
// additional initialization tasks to do in addition to the
// ones that FileDialog's constructor takes care of.
/// <summary>
/// Initializes a new instance of the SaveFileDialog class.
/// </summary>
public SaveFileDialog() : base()
{
Initialize();
}
#endregion Constructors
//---------------------------------------------------
//
// Public Methods
//
//---------------------------------------------------
#region Public Methods
/// <summary>
/// Opens the file selected by the user with read-only permission.
/// </summary>
/// The filename used to open the file is the first element of the
/// FileNamesInternal array.
/// <exception cref="System.InvalidOperationException">
/// Thrown if there are no filenames stored in the SaveFileDialog.
/// </exception>
/// <Remarks>
/// Callers must have UIPermission.AllWindows to call this API.
/// </Remarks>
public Stream OpenFile()
{
// Extract the first filename from the ItemNames list.
string filename = CriticalItemName;
// If we got an empty or null filename, throw an exception to
// tell the user we don't have any files to open.
if (string.IsNullOrEmpty(filename))
{
throw new InvalidOperationException(SR.FileNameMustNotBeNull);
}
// Create a new FileStream from the file and return it.
return new FileStream(filename, FileMode.Create, FileAccess.ReadWrite);
}
//
// We override the FileDialog implementation to set a default
// for FOS_FILEMUSTEXIST in addition to the other option flags
// defined in FileDialog.
/// <summary>
/// Resets all properties to their default values.
/// </summary>
/// <Remarks>
/// Callers must have UIPermission.AllWindows to call this API.
/// </Remarks>
public override void Reset()
{
// it is VERY important that the base.reset() call remain here
// and be located at the top of this function.
// Since most of the initialization for this class is actually
// done in the FileDialog class, we must call that implementation
// before we can finish with the Initialize() call specific to our
// derived class.
base.Reset();
Initialize();
}
#endregion Public Methods
//---------------------------------------------------
//
// Public Properties
//
//---------------------------------------------------
#region Public Properties
// If the user specifies a file that does not exist, this flag causes our code
// to prompt the user for permission to create the file. If the user chooses
// to create the file, the dialog box closes and the function returns the
// specified name; otherwise, the dialog box remains open.
//
// We use our own prompt, so not using FOS_CREATEPROMPT (which is for open dialogs only).
//
/// <summary>
/// Gets or sets a value indicating whether the dialog box prompts the user for
/// permission to create a file if the user specifies a file that does not exist.
/// </summary>
/// <Remarks>
/// Callers must have UIPermission.AllWindows to call this API.
/// </Remarks>
public bool CreatePrompt { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the dialog box will attempt to create
/// a test file at the selected path (default is true). If this flag is not set,
/// the calling application must handle errors, such as denial of access,
/// discovered when the item is created.
/// </summary>
public bool CreateTestFile
{
get
{
return !GetOption(FOS.NOTESTFILECREATE);
}
set
{
SetOption(FOS.NOTESTFILECREATE, !value);
}
}
// Causes our code to generate a message box if the selected file already
// exists. The user must confirm whether to overwrite the file.
//
// We use our own prompt, so not using FOS_OVERWRITEPROMPT (for backward compatibility).
//
/// <summary>
/// Gets or sets a value indicating whether the Save As dialog box displays a
/// warning if the user specifies a file name that already exists.
/// </summary>
/// <Remarks>
/// Callers must have UIPermission.AllWindows to call this API.
/// </Remarks>
public bool OverwritePrompt { get; set; }
#endregion Public Properties
//---------------------------------------------------
//
// Public Events
//
//---------------------------------------------------
//#region Public Events
//#endregion Public Events
//---------------------------------------------------
//
// Protected Methods
//
//---------------------------------------------------
//#region Protected Methods
//#endregion Protected Methods
//---------------------------------------------------
//
// Internal Methods
//
//---------------------------------------------------
#region Internal Methods
/// <summary>
/// PromptUserIfAppropriate overrides a virtual function from FileDialog that show
/// message boxes (like "Do you want to overwrite this file") necessary after
/// the Save button is pressed in a file dialog.
///
/// Return value is false if we showed a dialog box and true if we did not.
/// (in other words, true if it's OK to continue with the save process and
/// false if we need to return the user to the dialog to make another selection.)
/// </summary>
/// <remarks>
/// We first call the base class implementation to deal with any messages handled there.
/// Then, if FOS_OVERWRITEPROMPT (for a message box if the selected file already exists)
/// or FOS_CREATEPROMPT (for a message box if a file is specified that does not exist)
/// flags are set, we check to see if it is appropriate to show the dialog(s) in this
/// method. If so, we then call PromptFileOverwrite or PromptFileCreate, respectively.
/// </remarks>
internal override bool PromptUserIfAppropriate(string fileName)
{
// First, call the FileDialog implementation of PromptUserIfAppropriate
// so any processing that happens there can occur. If it returns false,
// we'll stop processing (to avoid showing more than one message box
// before returning control to the user) and return false as well.
if (!base.PromptUserIfAppropriate(fileName))
{
return false;
}
bool fExist = File.Exists(fileName);
// If the file does not exist, check if CreatePrompt is
// set. If so, display the appropriate message box and act
// on the user's choice.
// Note that File.Exists requires a full path as a parameter.
if (CreatePrompt && !fExist)
{
if (!PromptFileCreate(fileName))
{
return false;
}
}
// If the file already exists, check if OverwritePrompt is
// set. If so, display the appropriate message box and act
// on the user's choice.
// Note that File.Exists requires a full path as a parameter.
if (OverwritePrompt && fExist)
{
if (!PromptFileOverwrite(fileName))
{
return false;
}
}
// Since all dialog boxes we showed resulted in a positive outcome,
// returning true allows the file dialog box to close.
return true;
}
private protected override IFileDialog CreateDialog()
{
return (IFileDialog)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID.FileSaveDialog)));
}
#endregion Internal Methods
//---------------------------------------------------
//
// Internal Properties
//
//---------------------------------------------------
//#region Internal Properties
//#endregion Internal Properties
//---------------------------------------------------
//
// Internal Events
//
//---------------------------------------------------
//#region Internal Events
//#endregion Internal Events
//---------------------------------------------------
//
// Private Methods
//
//---------------------------------------------------
#region Private Methods
// Provides the actual implementation of initialization tasks.
// Initialize() is called from both the constructor and the
// public Reset() function to set default values for member
// variables and for the options bitmask.
//
// We only perform SaveFileDialog() specific reset tasks here;
// it's the calling code's responsibility to ensure that the
// base is initialized first.
private void Initialize()
{
// Causes the Save As dialog box to generate a message box if
// the selected file already exists. The user must confirm
// whether to overwrite the file. Default is true.
OverwritePrompt = true;
}
/// <summary>
/// Prompts the user with a System.Windows.MessageBox
/// when a file is about to be created. This method is
/// invoked when the CreatePrompt property is true and the specified file
/// does not exist. A return value of false prevents the dialog from closing.
/// </summary>
private bool PromptFileCreate(string fileName)
{
return MessageBoxWithFocusRestore(SR.Format(SR.FileDialogCreatePrompt, fileName),
MessageBoxButton.YesNo, MessageBoxImage.Warning);
}
/// <summary>
/// Prompts the user when a file is about to be overwritten. This method is
/// invoked when the "overwritePrompt" property is true and the specified
/// file already exists. A return value of false prevents the dialog from
/// closing.
/// </summary>
private bool PromptFileOverwrite(string fileName)
{
return MessageBoxWithFocusRestore(SR.Format(SR.FileDialogOverwritePrompt, fileName),
MessageBoxButton.YesNo, MessageBoxImage.Warning);
}
#endregion Private Methods
//---------------------------------------------------
//
// Private Properties
//
//---------------------------------------------------
//#region Private Properties
//#endregion Private Properties
//---------------------------------------------------
//
// Private Fields
//
//---------------------------------------------------
//#region Private Fields
//#endregion Private Fields
}
}
|