Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide overloads for an Win32 handle as owning window (augustoproiete/ookii-dialogs-wpf#18) #19

Merged
merged 1 commit into from
Oct 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 50 additions & 3 deletions src/Ookii.Dialogs.Wpf/CredentialDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ public bool ShowDialog()
/// <summary>
/// Shows the credentials dialog as a modal dialog with the specified owner.
/// </summary>
/// <param name="owner">The <see cref="Window"/> that owns the credentials dialog.</param>
/// <param name="owner">The <see cref="IntPtr"/> Win32 handle that owns the credentials dialog.</param>
/// <returns><see langword="true" /> if the user clicked OK; otherwise, <see langword="false" />.</returns>
/// <remarks>
/// <para>
Expand Down Expand Up @@ -422,11 +422,13 @@ public bool ShowDialog()
/// <exception cref="CredentialException">An error occurred while showing the credentials dialog.</exception>
/// <exception cref="InvalidOperationException"><see cref="Target"/> is an empty string ("").</exception>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public bool ShowDialog(Window owner)
public bool ShowDialog(IntPtr owner)
{
if( string.IsNullOrEmpty(_target) )
throw new InvalidOperationException(Properties.Resources.CredentialEmptyTargetError);

IntPtr ownerHandle = owner == default(IntPtr) ? NativeMethods.GetActiveWindow() : owner;

UserName = "";
Password = "";
IsStoredCredential = false;
Expand All @@ -451,7 +453,6 @@ public bool ShowDialog(Window owner)
storedCredentials = true;
}

IntPtr ownerHandle = owner == null ? NativeMethods.GetActiveWindow() : new WindowInteropHelper(owner).Handle;
bool result;
if( NativeMethods.IsWindowsVistaOrLater )
result = PromptForCredentialsCredUIWin(ownerHandle, storedCredentials);
Expand All @@ -460,6 +461,52 @@ public bool ShowDialog(Window owner)
return result;
}

/// <summary>
/// Shows the credentials dialog as a modal dialog with the specified owner.
/// </summary>
/// <param name="owner">The <see cref="Window"/> that owns the credentials dialog.</param>
/// <returns><see langword="true" /> if the user clicked OK; otherwise, <see langword="false" />.</returns>
/// <remarks>
/// <para>
/// The credentials dialog will not be shown if one of the following conditions holds:
/// </para>
/// <list type="bullet">
/// <item>
/// <description>
/// <see cref="UseApplicationInstanceCredentialCache"/> is <see langword="true"/> and the application instance
/// credential cache contains credentials for the specified <see cref="Target"/>, even if <see cref="ShowUIForSavedCredentials"/>
/// is <see langword="true"/>.
/// </description>
/// </item>
/// <item>
/// <description>
/// <see cref="ShowSaveCheckBox"/> is <see langword="true"/>, <see cref="ShowUIForSavedCredentials"/> is <see langword="false"/>, and the operating system credential store
/// for the current user contains credentials for the specified <see cref="Target"/>.
/// </description>
/// </item>
/// </list>
/// <para>
/// In these cases, the <see cref="Credentials"/>, <see cref="UserName"/> and <see cref="Password"/> properties will
/// be set to the saved credentials and this function returns immediately, returning <see langword="true" />.
/// </para>
/// <para>
/// If the <see cref="ShowSaveCheckBox"/> property is <see langword="true"/>, you should call <see cref="ConfirmCredentials"/>
/// after validating if the provided credentials are correct.
/// </para>
/// </remarks>
/// <exception cref="CredentialException">An error occurred while showing the credentials dialog.</exception>
/// <exception cref="InvalidOperationException"><see cref="Target"/> is an empty string ("").</exception>
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public bool ShowDialog(Window owner)
{
IntPtr ownerHandle;
if( owner == null )
ownerHandle = NativeMethods.GetActiveWindow();
else
ownerHandle = new WindowInteropHelper(owner).Handle;
return ShowDialog(ownerHandle);
}

/// <summary>
/// Confirms the validity of the credential provided by the user.
/// </summary>
Expand Down
63 changes: 63 additions & 0 deletions src/Ookii.Dialogs.Wpf/ProgressDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,37 @@ public void ShowDialog(Window owner)
ShowDialog(owner, null);
}

/// <summary>
/// Displays the progress dialog as a modal dialog.
/// </summary>
/// <param name="owner">The <see cref="IntPtr"/> Win32 handle that is the owner of this dialog.</param>
/// <remarks>
/// <para>
/// The ShowDialog function for most .Net dialogs will not return until the dialog is closed. However,
/// the <see cref="ShowDialog()"/> function for the <see cref="ProgressDialog"/> class will return immediately.
/// The parent window will be disabled as with all modal dialogs.
/// </para>
/// <para>
/// Although this function returns immediately, you cannot use the UI thread to do any processing. The dialog
/// will not function correctly unless the UI thread continues to handle window messages, so that thread may
/// not be blocked by some other activity. All processing related to the progress dialog must be done in
/// the <see cref="DoWork"/> event handler.
/// </para>
/// <para>
/// The progress dialog's window will appear in the taskbar. This behaviour is also contrary to most .Net dialogs,
/// but is part of the underlying native progress dialog API so cannot be avoided.
/// </para>
/// <para>
/// When possible, it is recommended that you use a modeless dialog using the <see cref="Show()"/> function.
/// </para>
/// </remarks>
/// <exception cref="InvalidOperationException">The animation specified in the <see cref="Animation"/> property
/// could not be loaded, or the operation is already running.</exception>
public void ShowDialog(IntPtr owner)
{
ShowDialog(owner, null);
}

/// <summary>
/// Displays the progress dialog as a modal dialog.
/// </summary>
Expand Down Expand Up @@ -519,6 +550,38 @@ public void ShowDialog(Window owner, object argument)
RunProgressDialog(owner == null ? NativeMethods.GetActiveWindow() : new WindowInteropHelper(owner).Handle, argument);
}

/// <summary>
/// Displays the progress dialog as a modal dialog.
/// </summary>
/// <param name="owner">The <see cref="IntPtr"/> Win32 handle that is the owner of this dialog.</param>
/// <param name="argument">A parameter for use by the background operation to be executed in the <see cref="DoWork"/> event handler.</param>
/// <remarks>
/// <para>
/// The ShowDialog function for most .Net dialogs will not return until the dialog is closed. However,
/// the <see cref="ShowDialog()"/> function for the <see cref="ProgressDialog"/> class will return immediately.
/// The parent window will be disabled as with all modal dialogs.
/// </para>
/// <para>
/// Although this function returns immediately, you cannot use the UI thread to do any processing. The dialog
/// will not function correctly unless the UI thread continues to handle window messages, so that thread may
/// not be blocked by some other activity. All processing related to the progress dialog must be done in
/// the <see cref="DoWork"/> event handler.
/// </para>
/// <para>
/// The progress dialog's window will appear in the taskbar. This behaviour is also contrary to most .Net dialogs,
/// but is part of the underlying native progress dialog API so cannot be avoided.
/// </para>
/// <para>
/// When possible, it is recommended that you use a modeless dialog using the <see cref="Show()"/> function.
/// </para>
/// </remarks>
/// <exception cref="InvalidOperationException">The animation specified in the <see cref="Animation"/> property
/// could not be loaded, or the operation is already running.</exception>
public void ShowDialog(IntPtr owner, object argument)
{
RunProgressDialog(owner == default(IntPtr) ? NativeMethods.GetActiveWindow() : owner, argument);
}

/// <summary>
/// Updates the dialog's progress bar.
/// </summary>
Expand Down
122 changes: 71 additions & 51 deletions src/Ookii.Dialogs.Wpf/TaskDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,76 @@ public TaskDialogButton ShowDialog(Window owner)
return ShowDialog(ownerHandle);
}

/// <summary>
/// Shows the task dialog as a modal dialog.
/// </summary>
/// <param name="owner">The <see cref="IntPtr"/> Win32 handle that is the owner of this task dialog.</param>
/// <returns>The button that the user clicked. Can be <see langword="null" /> if the user cancelled the dialog using the
/// title bar close button.</returns>
/// <exception cref="InvalidOperationException">
/// <para>
/// One of the properties or a combination of properties is not valid.
/// </para>
/// <para>
/// -or-
/// </para>
/// <para>
/// The dialog is already running.
/// </para>
/// </exception>
/// <exception cref="NotSupportedException">Task dialogs are not supported on the current operating system.</exception>
/// <exception cref="InvalidOperationException">Thrown if task dialog is already being displayed.</exception>
/// <exception cref="InvalidOperationException">Thrown if no buttons are present.</exception>
public TaskDialogButton ShowDialog(IntPtr owner)
{
if( !OSSupportsTaskDialogs )
throw new NotSupportedException(Properties.Resources.TaskDialogsNotSupportedError);

if( IsDialogRunning )
throw new InvalidOperationException(Properties.Resources.TaskDialogRunningError);

if( _buttons.Count == 0 )
throw new InvalidOperationException(Properties.Resources.TaskDialogNoButtonsError);

_config.hwndParent = owner;
_config.dwCommonButtons = 0;
_config.pButtons = IntPtr.Zero;
_config.cButtons = 0;
List<NativeMethods.TASKDIALOG_BUTTON> buttons = SetupButtons();
List<NativeMethods.TASKDIALOG_BUTTON> radioButtons = SetupRadioButtons();

SetupIcon();

try
{
MarshalButtons(buttons, out _config.pButtons, out _config.cButtons);
MarshalButtons(radioButtons, out _config.pRadioButtons, out _config.cRadioButtons);
int buttonId;
int radioButton;
bool verificationFlagChecked;
using( new ComCtlv6ActivationContext(true) )
{
NativeMethods.TaskDialogIndirect(ref _config, out buttonId, out radioButton, out verificationFlagChecked);
}
IsVerificationChecked = verificationFlagChecked;

TaskDialogRadioButton selectedRadioButton;
if( _radioButtonsById.TryGetValue(radioButton, out selectedRadioButton) )
selectedRadioButton.Checked = true;

TaskDialogButton selectedButton;
if( _buttonsById.TryGetValue(buttonId, out selectedButton) )
return selectedButton;
else
return null;
}
finally
{
CleanUpButtons(ref _config.pButtons, ref _config.cButtons);
CleanUpButtons(ref _config.pRadioButtons, ref _config.cRadioButtons);
}
}

/// <summary>
/// Simulates a click on the verification checkbox of the <see cref="TaskDialog"/>, if it exists.
/// </summary>
Expand Down Expand Up @@ -1220,57 +1290,7 @@ internal void ClickItem(TaskDialogItem item)
#endregion

#region Private members

private TaskDialogButton ShowDialog(IntPtr owner)
{
if( !OSSupportsTaskDialogs )
throw new NotSupportedException(Properties.Resources.TaskDialogsNotSupportedError);

if( IsDialogRunning )
throw new InvalidOperationException(Properties.Resources.TaskDialogRunningError);

if( _buttons.Count == 0 )
throw new InvalidOperationException(Properties.Resources.TaskDialogNoButtonsError);

_config.hwndParent = owner;
_config.dwCommonButtons = 0;
_config.pButtons = IntPtr.Zero;
_config.cButtons = 0;
List<NativeMethods.TASKDIALOG_BUTTON> buttons = SetupButtons();
List<NativeMethods.TASKDIALOG_BUTTON> radioButtons = SetupRadioButtons();

SetupIcon();

try
{
MarshalButtons(buttons, out _config.pButtons, out _config.cButtons);
MarshalButtons(radioButtons, out _config.pRadioButtons, out _config.cRadioButtons);
int buttonId;
int radioButton;
bool verificationFlagChecked;
using( new ComCtlv6ActivationContext(true) )
{
NativeMethods.TaskDialogIndirect(ref _config, out buttonId, out radioButton, out verificationFlagChecked);
}
IsVerificationChecked = verificationFlagChecked;

TaskDialogRadioButton selectedRadioButton;
if( _radioButtonsById.TryGetValue(radioButton, out selectedRadioButton) )
selectedRadioButton.Checked = true;

TaskDialogButton selectedButton;
if( _buttonsById.TryGetValue(buttonId, out selectedButton) )
return selectedButton;
else
return null;
}
finally
{
CleanUpButtons(ref _config.pButtons, ref _config.cButtons);
CleanUpButtons(ref _config.pRadioButtons, ref _config.cRadioButtons);
}
}


internal void UpdateDialog()
{
if( IsDialogRunning )
Expand Down
13 changes: 12 additions & 1 deletion src/Ookii.Dialogs.Wpf/VistaFileDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -542,10 +542,21 @@ public virtual void Reset()
else
{
IntPtr ownerHandle = owner == null ? NativeMethods.GetActiveWindow() : new WindowInteropHelper(owner).Handle;
return new bool?(RunFileDialog(ownerHandle));
return ShowDialog(ownerHandle);
}
}

/// <summary>
/// Displays the file dialog.
/// </summary>
/// <param name="owner">The <see cref="IntPtr"/> Win32 handle that is the owner of this dialog.</param>
/// <returns>If the user clicks the OK button of the dialog that is displayed (e.g. <see cref="VistaOpenFileDialog" />, <see cref="VistaSaveFileDialog" />), <see langword="true" /> is returned; otherwise, <see langword="false" />.</returns>
public bool? ShowDialog(IntPtr owner)
{
IntPtr ownerHandle = owner == default(IntPtr) ? NativeMethods.GetActiveWindow() : owner;
return new bool?(RunFileDialog(ownerHandle));
}

#endregion

#region Protected Methods
Expand Down
11 changes: 11 additions & 0 deletions src/Ookii.Dialogs.Wpf/VistaFolderBrowserDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,17 @@ public void Reset()
public bool? ShowDialog(Window owner)
{
IntPtr ownerHandle = owner == null ? NativeMethods.GetActiveWindow() : new WindowInteropHelper(owner).Handle;
return ShowDialog(ownerHandle);
}

/// <summary>
/// Displays the folder browser dialog.
/// </summary>
/// <param name="owner">The <see cref="IntPtr"/> Win32 handle that is the owner of this dialog.</param>
/// <returns>If the user clicks the OK button, <see langword="true" /> is returned; otherwise, <see langword="false" />.</returns>
public bool? ShowDialog(IntPtr owner)
{
IntPtr ownerHandle = owner == default(IntPtr) ? NativeMethods.GetActiveWindow() : owner;
return new bool?(IsVistaFolderDialogSupported ? RunDialog(ownerHandle) : RunDialogDownlevel(ownerHandle));
}

Expand Down