mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
b02427417c
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@5614 21ef857c-d57f-4fe0-8362-d861dc6d29cd
1223 lines
55 KiB
C#
1223 lines
55 KiB
C#
//------------------------------------------------------------------
|
||
// <summary>
|
||
// A P/Invoke wrapper for TaskDialog. Usability was given preference to perf and size.
|
||
// </summary>
|
||
//
|
||
// <remarks/>
|
||
//------------------------------------------------------------------
|
||
|
||
namespace ProcessHacker.Components
|
||
{
|
||
using System;
|
||
using System.Diagnostics.CodeAnalysis;
|
||
using System.Drawing;
|
||
using System.Runtime.InteropServices;
|
||
using System.Windows.Forms;
|
||
|
||
/// <summary>
|
||
/// The signature of the callback that recieves notificaitons from the Task Dialog.
|
||
/// </summary>
|
||
/// <param name="taskDialog">The active task dialog which has methods that can be performed on an active Task Dialog.</param>
|
||
/// <param name="args">The notification arguments including the type of notification and information for the notification.</param>
|
||
/// <param name="callbackData">The value set on TaskDialog.CallbackData</param>
|
||
/// <returns>Return value meaning varies depending on the Notification member of args.</returns>
|
||
public delegate bool TaskDialogCallback(ActiveTaskDialog taskDialog, TaskDialogNotificationArgs args, object callbackData);
|
||
|
||
/// <summary>
|
||
/// The TaskDialog common button flags used to specify the builtin bottons to show in the TaskDialog.
|
||
/// </summary>
|
||
[Flags]
|
||
public enum TaskDialogCommonButtons
|
||
{
|
||
/// <summary>
|
||
/// No common buttons.
|
||
/// </summary>
|
||
None = 0,
|
||
|
||
/// <summary>
|
||
/// OK common button. If selected Task Dialog will return DialogResult.OK.
|
||
/// </summary>
|
||
Ok = 0x0001,
|
||
|
||
/// <summary>
|
||
/// Yes common button. If selected Task Dialog will return DialogResult.Yes.
|
||
/// </summary>
|
||
Yes = 0x0002,
|
||
|
||
/// <summary>
|
||
/// No common button. If selected Task Dialog will return DialogResult.No.
|
||
/// </summary>
|
||
No = 0x0004,
|
||
|
||
/// <summary>
|
||
/// Cancel common button. If selected Task Dialog will return DialogResult.Cancel.
|
||
/// If this button is specified, the dialog box will respond to typical cancel actions (Alt-F4 and Escape).
|
||
/// </summary>
|
||
Cancel = 0x0008,
|
||
|
||
/// <summary>
|
||
/// Retry common button. If selected Task Dialog will return DialogResult.Retry.
|
||
/// </summary>
|
||
Retry = 0x0010,
|
||
|
||
/// <summary>
|
||
/// Close common button. If selected Task Dialog will return this value.
|
||
/// </summary>
|
||
Close = 0x0020,
|
||
}
|
||
|
||
/// <summary>
|
||
/// The System icons the TaskDialog supports.
|
||
/// </summary>
|
||
public enum TaskDialogIcon : uint
|
||
{
|
||
/// <summary>
|
||
/// No Icon.
|
||
/// </summary>
|
||
None = 0,
|
||
|
||
/// <summary>
|
||
/// System warning icon.
|
||
/// </summary>
|
||
Warning = 0xFFFF, // MAKEINTRESOURCEW(-1)
|
||
|
||
/// <summary>
|
||
/// System Error icon.
|
||
/// </summary>
|
||
Error = 0xFFFE, // MAKEINTRESOURCEW(-2)
|
||
|
||
/// <summary>
|
||
/// System Information icon.
|
||
/// </summary>
|
||
Information = 0xFFFD, // MAKEINTRESOURCEW(-3)
|
||
|
||
/// <summary>
|
||
/// Shield icon.
|
||
/// </summary>
|
||
Shield = 0xFFFC, // MAKEINTRESOURCEW(-4)
|
||
|
||
//These are undocumented "Special Styled" TaskDialog Windows
|
||
SecurityStop = UInt16.MaxValue - 1,
|
||
SecurityInformation = UInt16.MaxValue - 2,
|
||
SecurityShield = UInt16.MaxValue - 3,
|
||
SecurityShieldBlue = UInt16.MaxValue - 4,
|
||
SecurityWarning = UInt16.MaxValue - 5,
|
||
SecurityError = UInt16.MaxValue - 6,
|
||
SecuritySuccess = UInt16.MaxValue - 7,
|
||
SecurityShieldGray = UInt16.MaxValue - 8,
|
||
ASecurityWarning = UInt16.MaxValue,
|
||
|
||
//Other undocumented Icons
|
||
DefragWithShield = 195,
|
||
VideoIconWithoutVideo = 193,
|
||
WorldIconWithCable = 179,
|
||
MagnifyingGlass = 177,
|
||
FolderwithTwoArrowsPointingInwards = 175,
|
||
AppInstallUninstallIcon = 161,
|
||
AppearanceIcon = 151,
|
||
PerformanceMonitorIcon = 150,
|
||
MyComputerIconWithTick = 149,
|
||
ComputerJumpToComputerIcon = 147,
|
||
MonitorIconWithMagnifingGlass = 145,
|
||
InternetWorldWithClockIcon = 144,
|
||
BriefcaseWithUsericon = 130,
|
||
AppPageWithTicks = 121,
|
||
NetworkingIcon = 120,
|
||
CogWithTicks = 114,
|
||
DegragIcon = 111,
|
||
ShowDesktopIcon = 110,
|
||
ExclamationMarkShield = 107,
|
||
GreenTickShield = 106,
|
||
RedXShield = 105,
|
||
QuestionIcon = 104,
|
||
MonitorIcon = 101,
|
||
RunBoxIcon = 100,
|
||
CirleQuestion = 99,
|
||
CircleX = 98,
|
||
GreySmallX = 97,
|
||
FlashChip = 96,
|
||
TXTandBRIcon = 94,
|
||
BigRedX = 89,
|
||
AppInstallIcon = 87,
|
||
ExIcon = 84,
|
||
KeyIcon = 82,
|
||
InfoIcon = 81,
|
||
Startmenu = 80,
|
||
SharedIcon = 79,
|
||
WindowsDrive = 37,
|
||
CircleandTick = 24,
|
||
Network = 25,
|
||
RecycleBin = 55,
|
||
Padlock = 59,
|
||
DisplayLookingIcon = 65,
|
||
Picture = 70,
|
||
HDDQuestion = 75,
|
||
}
|
||
|
||
/// <summary>
|
||
/// Task Dialog callback notifications.
|
||
/// </summary>
|
||
public enum TaskDialogNotification
|
||
{
|
||
/// <summary>
|
||
/// Sent by the Task Dialog once the dialog has been created and before it is displayed.
|
||
/// The value returned by the callback is ignored.
|
||
/// </summary>
|
||
Created = 0,
|
||
|
||
//// Spec is not clear what this is so not supporting it.
|
||
///// <summary>
|
||
///// Sent by the Task Dialog when a navigation has occurred.
|
||
///// The value returned by the callback is ignored.
|
||
///// </summary>
|
||
// Navigated = 1,
|
||
|
||
/// <summary>
|
||
/// Sent by the Task Dialog when the user selects a button or command link in the task dialog.
|
||
/// The button ID corresponding to the button selected will be available in the
|
||
/// TaskDialogNotificationArgs. To prevent the Task Dialog from closing, the application must
|
||
/// return true, otherwise the Task Dialog will be closed and the button ID returned to via
|
||
/// the original application call.
|
||
/// </summary>
|
||
ButtonClicked = 2, // wParam = Button ID
|
||
|
||
/// <summary>
|
||
/// Sent by the Task Dialog when the user clicks on a hyperlink in the Task Dialog’s content.
|
||
/// The string containing the HREF of the hyperlink will be available in the
|
||
/// TaskDialogNotificationArgs. To prevent the TaskDialog from shell executing the hyperlink,
|
||
/// the application must return TRUE, otherwise ShellExecute will be called.
|
||
/// </summary>
|
||
HyperlinkClicked = 3, // lParam = (LPCWSTR)pszHREF
|
||
|
||
/// <summary>
|
||
/// Sent by the Task Dialog approximately every 200 milliseconds when TaskDialog.CallbackTimer
|
||
/// has been set to true. The number of milliseconds since the dialog was created or the
|
||
/// notification returned true is available on the TaskDialogNotificationArgs. To reset
|
||
/// the tickcount, the application must return true, otherwise the tickcount will continue to
|
||
/// increment.
|
||
/// </summary>
|
||
Timer = 4, // wParam = Milliseconds since dialog created or timer reset
|
||
|
||
/// <summary>
|
||
/// Sent by the Task Dialog when it is destroyed and its window handle no longer valid.
|
||
/// The value returned by the callback is ignored.
|
||
/// </summary>
|
||
Destroyed = 5,
|
||
|
||
/// <summary>
|
||
/// Sent by the Task Dialog when the user selects a radio button in the task dialog.
|
||
/// The button ID corresponding to the button selected will be available in the
|
||
/// TaskDialogNotificationArgs.
|
||
/// The value returned by the callback is ignored.
|
||
/// </summary>
|
||
RadioButtonClicked = 6, // wParam = Radio Button ID
|
||
|
||
/// <summary>
|
||
/// Sent by the Task Dialog once the dialog has been constructed and before it is displayed.
|
||
/// The value returned by the callback is ignored.
|
||
/// </summary>
|
||
DialogConstructed = 7,
|
||
|
||
/// <summary>
|
||
/// Sent by the Task Dialog when the user checks or unchecks the verification checkbox.
|
||
/// The verificationFlagChecked value is available on the TaskDialogNotificationArgs.
|
||
/// The value returned by the callback is ignored.
|
||
/// </summary>
|
||
VerificationClicked = 8, // wParam = 1 if checkbox checked, 0 if not, lParam is unused and always 0
|
||
|
||
/// <summary>
|
||
/// Sent by the Task Dialog when the user presses F1 on the keyboard while the dialog has focus.
|
||
/// The value returned by the callback is ignored.
|
||
/// </summary>
|
||
Help = 9,
|
||
|
||
/// <summary>
|
||
/// Sent by the task dialog when the user clicks on the dialog's expando button.
|
||
/// The expanded value is available on the TaskDialogNotificationArgs.
|
||
/// The value returned by the callback is ignored.
|
||
/// </summary>
|
||
ExpandoButtonClicked = 10 // wParam = 0 (dialog is now collapsed), wParam != 0 (dialog is now expanded)
|
||
}
|
||
|
||
/// <summary>
|
||
/// Progress bar state.
|
||
/// </summary>
|
||
public enum ProgressBarState
|
||
{
|
||
/// <summary>
|
||
/// Normal.
|
||
/// </summary>
|
||
Normal = 1,
|
||
|
||
/// <summary>
|
||
/// Error state.
|
||
/// </summary>
|
||
Error = 2,
|
||
|
||
/// <summary>
|
||
/// Paused state.
|
||
/// </summary>
|
||
Paused = 3
|
||
}
|
||
|
||
/// <summary>
|
||
/// A custom button for the TaskDialog.
|
||
/// </summary>
|
||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
|
||
public struct TaskDialogButton
|
||
{
|
||
/// <summary>
|
||
/// The ID of the button. This value is returned by TaskDialog.Show when the button is clicked.
|
||
/// </summary>
|
||
private int buttonId;
|
||
|
||
/// <summary>
|
||
/// The string that appears on the button.
|
||
/// </summary>
|
||
[MarshalAs(UnmanagedType.LPWStr)]
|
||
private string buttonText;
|
||
|
||
/// <summary>
|
||
/// Initialize the custom button.
|
||
/// </summary>
|
||
/// <param name="id">The ID of the button. This value is returned by TaskDialog.Show when
|
||
/// the button is clicked. Typically this will be a value in the DialogResult enum.</param>
|
||
/// <param name="text">The string that appears on the button.</param>
|
||
public TaskDialogButton(int id, string text)
|
||
{
|
||
this.buttonId = id;
|
||
this.buttonText = text;
|
||
}
|
||
|
||
/// <summary>
|
||
/// The ID of the button. This value is returned by TaskDialog.Show when the button is clicked.
|
||
/// </summary>
|
||
public int ButtonId
|
||
{
|
||
get { return this.buttonId; }
|
||
set { this.buttonId = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// The string that appears on the button.
|
||
/// </summary>
|
||
public string ButtonText
|
||
{
|
||
get { return this.buttonText; }
|
||
set { this.buttonText = value; }
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// A Task Dialog. This is like a MessageBox but with many more features. TaskDialog requires Windows Longhorn or later.
|
||
/// </summary>
|
||
public class TaskDialog
|
||
{
|
||
/// <summary>
|
||
/// The string to be used for the dialog box title. If this parameter is NULL, the filename of the executable program is used.
|
||
/// </summary>
|
||
private string windowTitle;
|
||
|
||
/// <summary>
|
||
/// The string to be used for the main instruction.
|
||
/// </summary>
|
||
private string mainInstruction;
|
||
|
||
/// <summary>
|
||
/// The string to be used for the dialog’s primary content. If the EnableHyperlinks member is true,
|
||
/// then this string may contain hyperlinks in the form: <A HREF="executablestring">Hyperlink Text</A>.
|
||
/// WARNING: Enabling hyperlinks when using content from an unsafe source may cause security vulnerabilities.
|
||
/// </summary>
|
||
private string content;
|
||
|
||
/// <summary>
|
||
/// Specifies the push buttons displayed in the dialog box. This parameter may be a combination of flags.
|
||
/// If no common buttons are specified and no custom buttons are specified using the Buttons member, the
|
||
/// dialog box will contain the OK button by default.
|
||
/// </summary>
|
||
private TaskDialogCommonButtons commonButtons;
|
||
|
||
/// <summary>
|
||
/// Specifies a built in icon for the main icon in the dialog. If this is set to none
|
||
/// and the CustomMainIcon is null then no main icon will be displayed.
|
||
/// </summary>
|
||
private TaskDialogIcon mainIcon;
|
||
|
||
/// <summary>
|
||
/// Specifies a custom in icon for the main icon in the dialog. If this is set to none
|
||
/// and the CustomMainIcon member is null then no main icon will be displayed.
|
||
/// </summary>
|
||
private Icon customMainIcon;
|
||
|
||
/// <summary>
|
||
/// Specifies a built in icon for the icon to be displayed in the footer area of the
|
||
/// dialog box. If this is set to none and the CustomFooterIcon member is null then no
|
||
/// footer icon will be displayed.
|
||
/// </summary>
|
||
private TaskDialogIcon footerIcon;
|
||
|
||
/// <summary>
|
||
/// Specifies a custom icon for the icon to be displayed in the footer area of the
|
||
/// dialog box. If this is set to none and the CustomFooterIcon member is null then no
|
||
/// footer icon will be displayed.
|
||
/// </summary>
|
||
private Icon customFooterIcon;
|
||
|
||
/// <summary>
|
||
/// Specifies the custom push buttons to display in the dialog. Use CommonButtons member for
|
||
/// common buttons; OK, Yes, No, Retry and Cancel, and Buttons when you want different text
|
||
/// on the push buttons.
|
||
/// </summary>
|
||
private TaskDialogButton[] buttons;
|
||
|
||
/// <summary>
|
||
/// Specifies the radio buttons to display in the dialog.
|
||
/// </summary>
|
||
private TaskDialogButton[] radioButtons;
|
||
|
||
/// <summary>
|
||
/// The flags passed to TaskDialogIndirect.
|
||
/// </summary>
|
||
private UnsafeNativeMethods.TASKDIALOG_FLAGS flags;
|
||
|
||
/// <summary>
|
||
/// Indicates the default button for the dialog. This may be any of the values specified
|
||
/// in ButtonId members of one of the TaskDialogButton structures in the Buttons array,
|
||
/// or one a DialogResult value that corresponds to a buttons specified in the CommonButtons Member.
|
||
/// If this member is zero or its value does not correspond to any button ID in the dialog,
|
||
/// then the first button in the dialog will be the default.
|
||
/// </summary>
|
||
private int defaultButton;
|
||
|
||
/// <summary>
|
||
/// Indicates the default radio button for the dialog. This may be any of the values specified
|
||
/// in ButtonId members of one of the TaskDialogButton structures in the RadioButtons array.
|
||
/// If this member is zero or its value does not correspond to any radio button ID in the dialog,
|
||
/// then the first button in RadioButtons will be the default.
|
||
/// The property NoDefaultRadioButton can be set to have no default.
|
||
/// </summary>
|
||
private int defaultRadioButton;
|
||
|
||
/// <summary>
|
||
/// The string to be used to label the verification checkbox. If this member is null, the
|
||
/// verification checkbox is not displayed in the dialog box.
|
||
/// </summary>
|
||
private string verificationText;
|
||
|
||
/// <summary>
|
||
/// The string to be used for displaying additional information. The additional information is
|
||
/// displayed either immediately below the content or below the footer text depending on whether
|
||
/// the ExpandFooterArea member is true. If the EnableHyperlinks member is true, then this string
|
||
/// may contain hyperlinks in the form: <A HREF="executablestring">Hyperlink Text</A>.
|
||
/// WARNING: Enabling hyperlinks when using content from an unsafe source may cause security vulnerabilities.
|
||
/// </summary>
|
||
private string expandedInformation;
|
||
|
||
/// <summary>
|
||
/// The string to be used to label the button for collapsing the expanded information. This
|
||
/// member is ignored when the ExpandedInformation member is null. If this member is null
|
||
/// and the CollapsedControlText is specified, then the CollapsedControlText value will be
|
||
/// used for this member as well.
|
||
/// </summary>
|
||
private string expandedControlText;
|
||
|
||
/// <summary>
|
||
/// The string to be used to label the button for expanding the expanded information. This
|
||
/// member is ignored when the ExpandedInformation member is null. If this member is null
|
||
/// and the ExpandedControlText is specified, then the ExpandedControlText value will be
|
||
/// used for this member as well.
|
||
/// </summary>
|
||
private string collapsedControlText;
|
||
|
||
/// <summary>
|
||
/// The string to be used in the footer area of the dialog box. If the EnableHyperlinks member
|
||
/// is true, then this string may contain hyperlinks in the form: <A HREF="executablestring">
|
||
/// Hyperlink Text</A>.
|
||
/// WARNING: Enabling hyperlinks when using content from an unsafe source may cause security vulnerabilities.
|
||
/// </summary>
|
||
private string footer;
|
||
|
||
/// <summary>
|
||
/// The callback that receives messages from the Task Dialog when various events occur.
|
||
/// </summary>
|
||
private TaskDialogCallback callback;
|
||
|
||
/// <summary>
|
||
/// Reference that is passed to the callback.
|
||
/// </summary>
|
||
private object callbackData;
|
||
|
||
/// <summary>
|
||
/// Specifies the width of the Task Dialog’s client area in DLU’s. If 0, Task Dialog will calculate the ideal width.
|
||
/// </summary>
|
||
private uint width;
|
||
|
||
/// <summary>
|
||
/// Creates a default Task Dialog.
|
||
/// </summary>
|
||
public TaskDialog()
|
||
{
|
||
this.Reset();
|
||
}
|
||
|
||
/// <summary>
|
||
/// The string to be used for the dialog box title. If this parameter is NULL, the filename of the executable program is used.
|
||
/// </summary>
|
||
public string WindowTitle
|
||
{
|
||
get { return this.windowTitle; }
|
||
set { this.windowTitle = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// The string to be used for the main instruction.
|
||
/// </summary>
|
||
public string MainInstruction
|
||
{
|
||
get { return this.mainInstruction; }
|
||
set { this.mainInstruction = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// The string to be used for the dialog’s primary content. If the EnableHyperlinks member is true,
|
||
/// then this string may contain hyperlinks in the form: <A HREF="executablestring">Hyperlink Text</A>.
|
||
/// WARNING: Enabling hyperlinks when using content from an unsafe source may cause security vulnerabilities.
|
||
/// </summary>
|
||
public string Content
|
||
{
|
||
get { return this.content; }
|
||
set { this.content = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Specifies the push buttons displayed in the dialog box. This parameter may be a combination of flags.
|
||
/// If no common buttons are specified and no custom buttons are specified using the Buttons member, the
|
||
/// dialog box will contain the OK button by default.
|
||
/// </summary>
|
||
public TaskDialogCommonButtons CommonButtons
|
||
{
|
||
get { return this.commonButtons; }
|
||
set { this.commonButtons = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Specifies a built in icon for the main icon in the dialog. If this is set to none
|
||
/// and the CustomMainIcon is null then no main icon will be displayed.
|
||
/// </summary>
|
||
public TaskDialogIcon MainIcon
|
||
{
|
||
get { return this.mainIcon; }
|
||
set { this.mainIcon = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Specifies a custom in icon for the main icon in the dialog. If this is set to none
|
||
/// and the CustomMainIcon member is null then no main icon will be displayed.
|
||
/// </summary>
|
||
public Icon CustomMainIcon
|
||
{
|
||
get { return this.customMainIcon; }
|
||
set { this.customMainIcon = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Specifies a built in icon for the icon to be displayed in the footer area of the
|
||
/// dialog box. If this is set to none and the CustomFooterIcon member is null then no
|
||
/// footer icon will be displayed.
|
||
/// </summary>
|
||
public TaskDialogIcon FooterIcon
|
||
{
|
||
get { return this.footerIcon; }
|
||
set { this.footerIcon = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Specifies a custom icon for the icon to be displayed in the footer area of the
|
||
/// dialog box. If this is set to none and the CustomFooterIcon member is null then no
|
||
/// footer icon will be displayed.
|
||
/// </summary>
|
||
public Icon CustomFooterIcon
|
||
{
|
||
get { return this.customFooterIcon; }
|
||
set { this.customFooterIcon = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Specifies the custom push buttons to display in the dialog. Use CommonButtons member for
|
||
/// common buttons; OK, Yes, No, Retry and Cancel, and Buttons when you want different text
|
||
/// on the push buttons.
|
||
/// </summary>
|
||
public TaskDialogButton[] Buttons
|
||
{
|
||
get
|
||
{
|
||
return this.buttons;
|
||
}
|
||
|
||
set
|
||
{
|
||
if (value == null)
|
||
{
|
||
throw new ArgumentNullException("value");
|
||
}
|
||
|
||
this.buttons = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Specifies the radio buttons to display in the dialog.
|
||
/// </summary>
|
||
public TaskDialogButton[] RadioButtons
|
||
{
|
||
get
|
||
{
|
||
return this.radioButtons;
|
||
}
|
||
|
||
set
|
||
{
|
||
if (value == null)
|
||
{
|
||
throw new ArgumentNullException("value");
|
||
}
|
||
|
||
this.radioButtons = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Enables hyperlink processing for the strings specified in the Content, ExpandedInformation
|
||
/// and FooterText members. When enabled, these members may be strings that contain hyperlinks
|
||
/// in the form: <A HREF="executablestring">Hyperlink Text</A>.
|
||
/// WARNING: Enabling hyperlinks when using content from an unsafe source may cause security vulnerabilities.
|
||
/// Note: Task Dialog will not actually execute any hyperlinks. Hyperlink execution must be handled
|
||
/// in the callback function specified by Callback member.
|
||
/// </summary>
|
||
public bool EnableHyperlinks
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_ENABLE_HYPERLINKS) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_ENABLE_HYPERLINKS, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the dialog should be able to be closed using Alt-F4, Escape and the title bar’s
|
||
/// close button even if no cancel button is specified in either the CommonButtons or Buttons members.
|
||
/// </summary>
|
||
public bool AllowDialogCancellation
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the buttons specified in the Buttons member should be displayed as command links
|
||
/// (using a standard task dialog glyph) instead of push buttons. When using command links, all
|
||
/// characters up to the first new line character in the ButtonText member (of the TaskDialogButton
|
||
/// structure) will be treated as the command link’s main text, and the remainder will be treated
|
||
/// as the command link’s note. This flag is ignored if the Buttons member has no entires.
|
||
/// </summary>
|
||
public bool UseCommandLinks
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the buttons specified in the Buttons member should be displayed as command links
|
||
/// (without a glyph) instead of push buttons. When using command links, all characters up to the
|
||
/// first new line character in the ButtonText member (of the TaskDialogButton structure) will be
|
||
/// treated as the command link’s main text, and the remainder will be treated as the command link’s
|
||
/// note. This flag is ignored if the Buttons member has no entires.
|
||
/// </summary>
|
||
public bool UseCommandLinksNoIcon
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS_NO_ICON) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS_NO_ICON, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the string specified by the ExpandedInformation member should be displayed at the
|
||
/// bottom of the dialog’s footer area instead of immediately after the dialog’s content. This flag
|
||
/// is ignored if the ExpandedInformation member is null.
|
||
/// </summary>
|
||
public bool ExpandFooterArea
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_EXPAND_FOOTER_AREA) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_EXPAND_FOOTER_AREA, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the string specified by the ExpandedInformation member should be displayed
|
||
/// when the dialog is initially displayed. This flag is ignored if the ExpandedInformation member
|
||
/// is null.
|
||
/// </summary>
|
||
public bool ExpandedByDefault
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_EXPANDED_BY_DEFAULT) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_EXPANDED_BY_DEFAULT, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the verification checkbox in the dialog should be checked when the dialog is
|
||
/// initially displayed. This flag is ignored if the VerificationText parameter is null.
|
||
/// </summary>
|
||
public bool VerificationFlagChecked
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that a Progress Bar should be displayed.
|
||
/// </summary>
|
||
public bool ShowProgressBar
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_SHOW_PROGRESS_BAR) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_SHOW_PROGRESS_BAR, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that an Marquee Progress Bar should be displayed.
|
||
/// </summary>
|
||
public bool ShowMarqueeProgressBar
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_SHOW_MARQUEE_PROGRESS_BAR) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_SHOW_MARQUEE_PROGRESS_BAR, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the TaskDialog’s callback should be called approximately every 200 milliseconds.
|
||
/// </summary>
|
||
public bool CallbackTimer
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_CALLBACK_TIMER) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_CALLBACK_TIMER, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the TaskDialog should be positioned (centered) relative to the owner window
|
||
/// passed when calling Show. If not set (or no owner window is passed), the TaskDialog is
|
||
/// positioned (centered) relative to the monitor.
|
||
/// </summary>
|
||
public bool PositionRelativeToWindow
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_POSITION_RELATIVE_TO_WINDOW) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_POSITION_RELATIVE_TO_WINDOW, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the TaskDialog should have right to left layout.
|
||
/// </summary>
|
||
public bool RightToLeftLayout
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_RTL_LAYOUT) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_RTL_LAYOUT, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the TaskDialog should have no default radio button.
|
||
/// </summary>
|
||
public bool NoDefaultRadioButton
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_NO_DEFAULT_RADIO_BUTTON) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_NO_DEFAULT_RADIO_BUTTON, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates that the TaskDialog can be minimised. Works only if there if parent window is null. Will enable cancellation also.
|
||
/// </summary>
|
||
public bool CanBeMinimized
|
||
{
|
||
get { return (this.flags & UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_CAN_BE_MINIMIZED) != 0; }
|
||
set { this.SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_CAN_BE_MINIMIZED, value); }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates the default button for the dialog. This may be any of the values specified
|
||
/// in ButtonId members of one of the TaskDialogButton structures in the Buttons array,
|
||
/// or one a DialogResult value that corresponds to a buttons specified in the CommonButtons Member.
|
||
/// If this member is zero or its value does not correspond to any button ID in the dialog,
|
||
/// then the first button in the dialog will be the default.
|
||
/// </summary>
|
||
public int DefaultButton
|
||
{
|
||
get { return this.defaultButton; }
|
||
set { this.defaultButton = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Indicates the default radio button for the dialog. This may be any of the values specified
|
||
/// in ButtonId members of one of the TaskDialogButton structures in the RadioButtons array.
|
||
/// If this member is zero or its value does not correspond to any radio button ID in the dialog,
|
||
/// then the first button in RadioButtons will be the default.
|
||
/// The property NoDefaultRadioButton can be set to have no default.
|
||
/// </summary>
|
||
public int DefaultRadioButton
|
||
{
|
||
get { return this.defaultRadioButton; }
|
||
set { this.defaultRadioButton = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// The string to be used to label the verification checkbox. If this member is null, the
|
||
/// verification checkbox is not displayed in the dialog box.
|
||
/// </summary>
|
||
public string VerificationText
|
||
{
|
||
get { return this.verificationText; }
|
||
set { this.verificationText = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// The string to be used for displaying additional information. The additional information is
|
||
/// displayed either immediately below the content or below the footer text depending on whether
|
||
/// the ExpandFooterArea member is true. If the EnameHyperlinks member is true, then this string
|
||
/// may contain hyperlinks in the form: <A HREF="executablestring">Hyperlink Text</A>.
|
||
/// WARNING: Enabling hyperlinks when using content from an unsafe source may cause security vulnerabilities.
|
||
/// </summary>
|
||
public string ExpandedInformation
|
||
{
|
||
get { return this.expandedInformation; }
|
||
set { this.expandedInformation = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// The string to be used to label the button for collapsing the expanded information. This
|
||
/// member is ignored when the ExpandedInformation member is null. If this member is null
|
||
/// and the CollapsedControlText is specified, then the CollapsedControlText value will be
|
||
/// used for this member as well.
|
||
/// </summary>
|
||
public string ExpandedControlText
|
||
{
|
||
get { return this.expandedControlText; }
|
||
set { this.expandedControlText = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// The string to be used to label the button for expanding the expanded information. This
|
||
/// member is ignored when the ExpandedInformation member is null. If this member is null
|
||
/// and the ExpandedControlText is specified, then the ExpandedControlText value will be
|
||
/// used for this member as well.
|
||
/// </summary>
|
||
public string CollapsedControlText
|
||
{
|
||
get { return this.collapsedControlText; }
|
||
set { this.collapsedControlText = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// The string to be used in the footer area of the dialog box. If the EnableHyperlinks member
|
||
/// is true, then this string may contain hyperlinks in the form: <A HREF="executablestring">
|
||
/// Hyperlink Text</A>.
|
||
/// WARNING: Enabling hyperlinks when using content from an unsafe source may cause security vulnerabilities.
|
||
/// </summary>
|
||
public string Footer
|
||
{
|
||
get { return this.footer; }
|
||
set { this.footer = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// width of the Task Dialog's client area in DLU's. If 0, Task Dialog will calculate the ideal width.
|
||
/// </summary>
|
||
public uint Width
|
||
{
|
||
get { return this.width; }
|
||
set { this.width = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// The callback that receives messages from the Task Dialog when various events occur.
|
||
/// </summary>
|
||
public TaskDialogCallback Callback
|
||
{
|
||
get { return this.callback; }
|
||
set { this.callback = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Reference that is passed to the callback.
|
||
/// </summary>
|
||
public object CallbackData
|
||
{
|
||
get { return this.callbackData; }
|
||
set { this.callbackData = value; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Resets the Task Dialog to the state when first constructed, all properties set to their default value.
|
||
/// </summary>
|
||
public void Reset()
|
||
{
|
||
this.windowTitle = null;
|
||
this.mainInstruction = null;
|
||
this.content = null;
|
||
this.commonButtons = 0;
|
||
this.mainIcon = TaskDialogIcon.None;
|
||
this.customMainIcon = null;
|
||
this.footerIcon = TaskDialogIcon.None;
|
||
this.customFooterIcon = null;
|
||
this.buttons = new TaskDialogButton[0];
|
||
this.radioButtons = new TaskDialogButton[0];
|
||
this.flags = 0;
|
||
this.defaultButton = 0;
|
||
this.defaultRadioButton = 0;
|
||
this.verificationText = null;
|
||
this.expandedInformation = null;
|
||
this.expandedControlText = null;
|
||
this.collapsedControlText = null;
|
||
this.footer = null;
|
||
this.callback = null;
|
||
this.callbackData = null;
|
||
this.width = 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates, displays, and operates a task dialog. The task dialog contains application-defined messages, title,
|
||
/// verification check box, command links and push buttons, plus any combination of predefined icons and push buttons
|
||
/// as specified on the other members of the class before calling Show.
|
||
/// </summary>
|
||
/// <returns>The result of the dialog, either a DialogResult value for common push buttons set in the CommonButtons
|
||
/// member or the ButtonID from a TaskDialogButton structure set on the Buttons member.</returns>
|
||
public int Show()
|
||
{
|
||
bool verificationFlagChecked;
|
||
int radioButtonResult;
|
||
return this.Show(IntPtr.Zero, out verificationFlagChecked, out radioButtonResult);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates, displays, and operates a task dialog. The task dialog contains application-defined messages, title,
|
||
/// verification check box, command links and push buttons, plus any combination of predefined icons and push buttons
|
||
/// as specified on the other members of the class before calling Show.
|
||
/// </summary>
|
||
/// <param name="owner">Owner window the task Dialog will modal to.</param>
|
||
/// <returns>The result of the dialog, either a DialogResult value for common push buttons set in the CommonButtons
|
||
/// member or the ButtonID from a TaskDialogButton structure set on the Buttons member.</returns>
|
||
public int Show(IWin32Window owner)
|
||
{
|
||
bool verificationFlagChecked;
|
||
int radioButtonResult;
|
||
return this.Show((owner == null ? IntPtr.Zero : owner.Handle), out verificationFlagChecked, out radioButtonResult);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates, displays, and operates a task dialog. The task dialog contains application-defined messages, title,
|
||
/// verification check box, command links and push buttons, plus any combination of predefined icons and push buttons
|
||
/// as specified on the other members of the class before calling Show.
|
||
/// </summary>
|
||
/// <param name="hwndOwner">Owner window the task Dialog will modal to.</param>
|
||
/// <returns>The result of the dialog, either a DialogResult value for common push buttons set in the CommonButtons
|
||
/// member or the ButtonID from a TaskDialogButton structure set on the Buttons member.</returns>
|
||
public int Show(IntPtr hwndOwner)
|
||
{
|
||
bool verificationFlagChecked;
|
||
int radioButtonResult;
|
||
return this.Show(hwndOwner, out verificationFlagChecked, out radioButtonResult);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates, displays, and operates a task dialog. The task dialog contains application-defined messages, title,
|
||
/// verification check box, command links and push buttons, plus any combination of predefined icons and push buttons
|
||
/// as specified on the other members of the class before calling Show.
|
||
/// </summary>
|
||
/// <param name="owner">Owner window the task Dialog will modal to.</param>
|
||
/// <param name="verificationFlagChecked">Returns true if the verification checkbox was checked when the dialog
|
||
/// was dismissed.</param>
|
||
/// <returns>The result of the dialog, either a DialogResult value for common push buttons set in the CommonButtons
|
||
/// member or the ButtonID from a TaskDialogButton structure set on the Buttons member.</returns>
|
||
public int Show(IWin32Window owner, out bool verificationFlagChecked)
|
||
{
|
||
int radioButtonResult;
|
||
return this.Show((owner == null ? IntPtr.Zero : owner.Handle), out verificationFlagChecked, out radioButtonResult);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates, displays, and operates a task dialog. The task dialog contains application-defined messages, title,
|
||
/// verification check box, command links and push buttons, plus any combination of predefined icons and push buttons
|
||
/// as specified on the other members of the class before calling Show.
|
||
/// </summary>
|
||
/// <param name="hwndOwner">Owner window the task Dialog will modal to.</param>
|
||
/// <param name="verificationFlagChecked">Returns true if the verification checkbox was checked when the dialog
|
||
/// was dismissed.</param>
|
||
/// <returns>The result of the dialog, either a DialogResult value for common push buttons set in the CommonButtons
|
||
/// member or the ButtonID from a TaskDialogButton structure set on the Buttons member.</returns>
|
||
public int Show(IntPtr hwndOwner, out bool verificationFlagChecked)
|
||
{
|
||
// We have to call a private version or PreSharp gets upset about a unsafe
|
||
// block in a public method. (PreSharp error 56505)
|
||
int radioButtonResult;
|
||
return this.PrivateShow(hwndOwner, out verificationFlagChecked, out radioButtonResult);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates, displays, and operates a task dialog. The task dialog contains application-defined messages, title,
|
||
/// verification check box, command links and push buttons, plus any combination of predefined icons and push buttons
|
||
/// as specified on the other members of the class before calling Show.
|
||
/// </summary>
|
||
/// <param name="owner">Owner window the task Dialog will modal to.</param>
|
||
/// <param name="verificationFlagChecked">Returns true if the verification checkbox was checked when the dialog
|
||
/// was dismissed.</param>
|
||
/// <param name="radioButtonResult">The radio botton selected by the user.</param>
|
||
/// <returns>The result of the dialog, either a DialogResult value for common push buttons set in the CommonButtons
|
||
/// member or the ButtonID from a TaskDialogButton structure set on the Buttons member.</returns>
|
||
public int Show(IWin32Window owner, out bool verificationFlagChecked, out int radioButtonResult)
|
||
{
|
||
return this.Show((owner == null ? IntPtr.Zero : owner.Handle), out verificationFlagChecked, out radioButtonResult);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates, displays, and operates a task dialog. The task dialog contains application-defined messages, title,
|
||
/// verification check box, command links and push buttons, plus any combination of predefined icons and push buttons
|
||
/// as specified on the other members of the class before calling Show.
|
||
/// </summary>
|
||
/// <param name="hwndOwner">Owner window the task Dialog will modal to.</param>
|
||
/// <param name="verificationFlagChecked">Returns true if the verification checkbox was checked when the dialog
|
||
/// was dismissed.</param>
|
||
/// <param name="radioButtonResult">The radio botton selected by the user.</param>
|
||
/// <returns>The result of the dialog, either a DialogResult value for common push buttons set in the CommonButtons
|
||
/// member or the ButtonID from a TaskDialogButton structure set on the Buttons member.</returns>
|
||
public int Show(IntPtr hwndOwner, out bool verificationFlagChecked, out int radioButtonResult)
|
||
{
|
||
// We have to call a private version or PreSharp gets upset about a unsafe
|
||
// block in a public method. (PreSharp error 56505)
|
||
return this.PrivateShow(hwndOwner, out verificationFlagChecked, out radioButtonResult);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Creates, displays, and operates a task dialog. The task dialog contains application-defined messages, title,
|
||
/// verification check box, command links and push buttons, plus any combination of predefined icons and push buttons
|
||
/// as specified on the other members of the class before calling Show.
|
||
/// </summary>
|
||
/// <param name="hwndOwner">Owner window the task Dialog will modal to.</param>
|
||
/// <param name="verificationFlagChecked">Returns true if the verification checkbox was checked when the dialog
|
||
/// was dismissed.</param>
|
||
/// <param name="radioButtonResult">The radio botton selected by the user.</param>
|
||
/// <returns>The result of the dialog, either a DialogResult value for common push buttons set in the CommonButtons
|
||
/// member or the ButtonID from a TaskDialogButton structure set on the Buttons member.</returns>
|
||
private int PrivateShow(IntPtr hwndOwner, out bool verificationFlagChecked, out int radioButtonResult)
|
||
{
|
||
verificationFlagChecked = false;
|
||
radioButtonResult = 0;
|
||
int result = 0;
|
||
UnsafeNativeMethods.TASKDIALOGCONFIG config = new UnsafeNativeMethods.TASKDIALOGCONFIG();
|
||
|
||
try
|
||
{
|
||
config.cbSize = (uint)Marshal.SizeOf(typeof(UnsafeNativeMethods.TASKDIALOGCONFIG));
|
||
config.hwndParent = hwndOwner;
|
||
config.dwFlags = this.flags;
|
||
config.dwCommonButtons = this.commonButtons;
|
||
|
||
if (!string.IsNullOrEmpty(this.windowTitle))
|
||
{
|
||
config.pszWindowTitle = this.windowTitle;
|
||
}
|
||
|
||
config.MainIcon = (IntPtr)this.mainIcon;
|
||
if (this.customMainIcon != null)
|
||
{
|
||
config.dwFlags |= UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_MAIN;
|
||
config.MainIcon = this.customMainIcon.Handle;
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(this.mainInstruction))
|
||
{
|
||
config.pszMainInstruction = this.mainInstruction;
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(this.content))
|
||
{
|
||
config.pszContent = this.content;
|
||
}
|
||
|
||
TaskDialogButton[] customButtons = this.buttons;
|
||
if (customButtons.Length > 0)
|
||
{
|
||
// Hand marshal the buttons array.
|
||
int elementSize = Marshal.SizeOf(typeof(TaskDialogButton));
|
||
config.pButtons = Marshal.AllocHGlobal(elementSize * (int)customButtons.Length);
|
||
for (int i = 0; i < customButtons.Length; i++)
|
||
{
|
||
unsafe // Unsafe because of pointer arithmatic.
|
||
{
|
||
byte* p = (byte*)config.pButtons;
|
||
Marshal.StructureToPtr(customButtons[i], (IntPtr)(p + (elementSize * i)), false);
|
||
}
|
||
|
||
config.cButtons++;
|
||
}
|
||
}
|
||
|
||
TaskDialogButton[] customRadioButtons = this.radioButtons;
|
||
if (customRadioButtons.Length > 0)
|
||
{
|
||
// Hand marshal the buttons array.
|
||
int elementSize = Marshal.SizeOf(typeof(TaskDialogButton));
|
||
config.pRadioButtons = Marshal.AllocHGlobal(elementSize * (int)customRadioButtons.Length);
|
||
for (int i = 0; i < customRadioButtons.Length; i++)
|
||
{
|
||
unsafe // Unsafe because of pointer arithmatic.
|
||
{
|
||
byte* p = (byte*)config.pRadioButtons;
|
||
Marshal.StructureToPtr(customRadioButtons[i], (IntPtr)(p + (elementSize * i)), false);
|
||
}
|
||
|
||
config.cRadioButtons++;
|
||
}
|
||
}
|
||
|
||
config.nDefaultButton = this.defaultButton;
|
||
config.nDefaultRadioButton = this.defaultRadioButton;
|
||
|
||
if (!string.IsNullOrEmpty(this.verificationText))
|
||
{
|
||
config.pszVerificationText = this.verificationText;
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(this.expandedInformation))
|
||
{
|
||
config.pszExpandedInformation = this.expandedInformation;
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(this.expandedControlText))
|
||
{
|
||
config.pszExpandedControlText = this.expandedControlText;
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(this.collapsedControlText))
|
||
{
|
||
config.pszCollapsedControlText = this.CollapsedControlText;
|
||
}
|
||
|
||
config.FooterIcon = (IntPtr)this.footerIcon;
|
||
if (this.customFooterIcon != null)
|
||
{
|
||
config.dwFlags |= UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_FOOTER;
|
||
config.FooterIcon = this.customFooterIcon.Handle;
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(this.footer))
|
||
{
|
||
config.pszFooter = this.footer;
|
||
}
|
||
|
||
// If our user has asked for a callback then we need to ask for one to
|
||
// translate to the friendly version.
|
||
if (this.callback != null)
|
||
{
|
||
config.pfCallback = new UnsafeNativeMethods.TaskDialogCallback(this.PrivateCallback);
|
||
}
|
||
|
||
////config.lpCallbackData = this.callbackData; // How do you do this? Need to pin the ref?
|
||
config.cxWidth = this.width;
|
||
|
||
// The call all this mucking about is here for.
|
||
UnsafeNativeMethods.TaskDialogIndirect(ref config, out result, out radioButtonResult, out verificationFlagChecked);
|
||
}
|
||
finally
|
||
{
|
||
// Free the unmanged memory needed for the button arrays.
|
||
// There is the possiblity of leaking memory if the app-domain is destroyed in a non clean way
|
||
// and the hosting OS process is kept alive but fixing this would require using hardening techniques
|
||
// that are not required for the users of this class.
|
||
if (config.pButtons != IntPtr.Zero)
|
||
{
|
||
int elementSize = Marshal.SizeOf(typeof(TaskDialogButton));
|
||
for (int i = 0; i < config.cButtons; i++)
|
||
{
|
||
unsafe
|
||
{
|
||
byte* p = (byte*)config.pButtons;
|
||
Marshal.DestroyStructure((IntPtr)(p + (elementSize * i)), typeof(TaskDialogButton));
|
||
}
|
||
}
|
||
|
||
Marshal.FreeHGlobal(config.pButtons);
|
||
}
|
||
|
||
if (config.pRadioButtons != IntPtr.Zero)
|
||
{
|
||
int elementSize = Marshal.SizeOf(typeof(TaskDialogButton));
|
||
for (int i = 0; i < config.cRadioButtons; i++)
|
||
{
|
||
unsafe
|
||
{
|
||
byte* p = (byte*)config.pRadioButtons;
|
||
Marshal.DestroyStructure((IntPtr)(p + (elementSize * i)), typeof(TaskDialogButton));
|
||
}
|
||
}
|
||
|
||
Marshal.FreeHGlobal(config.pRadioButtons);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// The callback from the native Task Dialog. This prepares the friendlier arguments and calls the simplier callback.
|
||
/// </summary>
|
||
/// <param name="hwnd">The window handle of the Task Dialog that is active.</param>
|
||
/// <param name="msg">The notification. A TaskDialogNotification value.</param>
|
||
/// <param name="wparam">Specifies additional noitification information. The contents of this parameter depends on the value of the msg parameter.</param>
|
||
/// <param name="lparam">Specifies additional noitification information. The contents of this parameter depends on the value of the msg parameter.</param>
|
||
/// <param name="refData">Specifies the application-defined value given in the call to TaskDialogIndirect.</param>
|
||
/// <returns>A HRESULT. It's not clear in the spec what a failed result will do.</returns>
|
||
private int PrivateCallback([In] IntPtr hwnd, [In] uint msg, [In] UIntPtr wparam, [In] IntPtr lparam, [In] IntPtr refData)
|
||
{
|
||
TaskDialogCallback callback = this.callback;
|
||
if (callback != null)
|
||
{
|
||
// Prepare arguments for the callback to the user we are insulating from Interop casting sillyness.
|
||
|
||
// Future: Consider reusing a single ActiveTaskDialog object and mark it as destroyed on the destry notification.
|
||
ActiveTaskDialog activeDialog = new ActiveTaskDialog(hwnd);
|
||
TaskDialogNotificationArgs args = new TaskDialogNotificationArgs();
|
||
args.Notification = (TaskDialogNotification)msg;
|
||
switch (args.Notification)
|
||
{
|
||
case TaskDialogNotification.ButtonClicked:
|
||
case TaskDialogNotification.RadioButtonClicked:
|
||
args.ButtonId = (int)wparam;
|
||
break;
|
||
case TaskDialogNotification.HyperlinkClicked:
|
||
args.Hyperlink = Marshal.PtrToStringUni(lparam);
|
||
break;
|
||
case TaskDialogNotification.Timer:
|
||
args.TimerTickCount = (uint)wparam;
|
||
break;
|
||
case TaskDialogNotification.VerificationClicked:
|
||
args.VerificationFlagChecked = (wparam != UIntPtr.Zero);
|
||
break;
|
||
case TaskDialogNotification.ExpandoButtonClicked:
|
||
args.Expanded = (wparam != UIntPtr.Zero);
|
||
break;
|
||
}
|
||
|
||
return (callback(activeDialog, args, this.callbackData) ? 1 : 0);
|
||
}
|
||
|
||
return 0; // false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Helper function to set or clear a bit in the flags field.
|
||
/// </summary>
|
||
/// <param name="flag">The Flag bit to set or clear.</param>
|
||
/// <param name="value">True to set, false to clear the bit in the flags field.</param>
|
||
private void SetFlag(UnsafeNativeMethods.TASKDIALOG_FLAGS flag, bool value)
|
||
{
|
||
if (value)
|
||
{
|
||
this.flags |= flag;
|
||
}
|
||
else
|
||
{
|
||
this.flags &= ~flag;
|
||
}
|
||
}
|
||
}
|
||
}
|