diff --git a/TaskDialogLib.nuspec b/TaskDialogLib.nuspec new file mode 100644 index 0000000..111ba43 --- /dev/null +++ b/TaskDialogLib.nuspec @@ -0,0 +1,29 @@ + + + + TaskDialogLib + 1.1.0.0 + TaskDialogLib + Florian Schneidereit + Flatcode.net + http://opensource.org/licenses/LGPL-2.1 + http://github.com/flatcode/TaskDialogLib + false + The TaskDialogLib is a thin wrapper library of the native Task Dialog Common Control introduced in Windows Vista for the .NET Framework and Windows Presentation Foundation. It allows you to declare task dialogs in XAML and define their logic in code-behind, including support for data binding with dependency properties. + A free and open source library for XAML-based Task Dialogs. + Ownership changed: TaskDialogLib is now being maintained by flatcode. Please note that in the course of this the XAML namespace changed from "http://github.com/sevenacids/TaskDialogLib" to "http://schemas.flatcode.net/2014/presentation". + +For a quick walkthrough how to use this library, see the CodeProject article: http://www.codeproject.com/Articles/751921/Introducing-TaskDialogLib-Task-Dialogs-in-XAML + Copyright © 2014 Flatcode.net. + + + + + + + + + + + + diff --git a/TaskDialogLib.sln b/TaskDialogLib.sln index a5bf304..f55278e 100644 --- a/TaskDialogLib.sln +++ b/TaskDialogLib.sln @@ -1,12 +1,17 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.30110.0 +# Visual Studio 15 +VisualStudioVersion = 15.0.27617.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaskDialogLib", "src\TaskDialogLib\TaskDialogLib.csproj", "{AFFBF61B-EA2F-4FC1-A40D-EE552246ADFB}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TaskDialogLibTest", "src\TaskDialogLibTest\TaskDialogLibTest.csproj", "{4EEAE5DC-CCCF-46E1-A357-297D4159A2C0}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{4B1E65E5-F2C6-40CC-A086-F9A777CA3649}" + ProjectSection(SolutionItems) = preProject + TaskDialogLib.nuspec = TaskDialogLib.nuspec + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -25,4 +30,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AE7BD9B4-D0FB-4272-BC36-91CDC57C74D2} + EndGlobalSection EndGlobal diff --git a/src/TaskDialogLib/TaskDialog.cs b/src/TaskDialogLib/TaskDialog.cs index b6d66ca..44a3152 100644 --- a/src/TaskDialogLib/TaskDialog.cs +++ b/src/TaskDialogLib/TaskDialog.cs @@ -24,6 +24,8 @@ * **************************************************************************************************/ +#nullable enable + #region Using Directives using System; @@ -39,1549 +41,1686 @@ namespace Flatcode.Presentation { - /// - /// Represents a dialog box that can be used to display information and receive simple input - /// from the user. - /// - /// - /// Like a , a task dialog is formatted by the operating system - /// according to properties you set. However, it offers many more features than a message box. - /// - [DefaultProperty("Content")] - [ContentProperty("Content")] - public class TaskDialog : DependencyObject - { - #region Fields - - readonly TaskDialogElementCollection buttons; - readonly TaskDialogElementCollection radioButtons; - - Boolean activated; - Boolean allowCancellation; - TaskDialogButtonStyle buttonStyle; - Boolean canMinimize; - TaskDialogButtons commonButtons; - Int32 defaultButton; - TaskDialogIcon defaultIcon; - Int32 defaultRadioButton; - TaskDialogState defaultState; - Boolean enableHyperlinks; - Boolean enableTimer; - Boolean expanded; - Boolean expandFooter; - IntPtr handle; - Boolean initialized; - TaskDialogProgressBar progressBar; - Window owner; - Boolean sizeToContent; - Boolean useDefaultIcon; - Boolean verificationChecked; - - IconHandle iconHandle; - IconHandle footerIconHandle; - - EventHandler activatedEventHandler; - EventHandler closedEventHandler; - EventHandler collapsedEventHandler; - EventHandler expandedEventHandler; - EventHandler helpEventHandler; - EventHandler initializedEventHandler; - EventHandler timerEventHandler; - EventHandler verificationChangedEventHandler; - - #endregion - - #region Fields: Dependency Properties - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty CollapsedControlTextProperty = - DependencyProperty.Register("CollapsedControlText", typeof(String), typeof(TaskDialog), - new PropertyMetadata(null)); - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty ContentProperty = - DependencyProperty.Register("Content", typeof(Object), typeof(TaskDialog), - new PropertyMetadata(null, ContentPropertyChanged)); - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty ExpandedControlTextProperty = - DependencyProperty.Register("ExpandedControlText", typeof(String), typeof(TaskDialog), - new PropertyMetadata(null)); - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty ExpandedInformationProperty = - DependencyProperty.Register("ExpandedInformation", typeof(Object), typeof(TaskDialog), - new PropertyMetadata(null, ExpandedInformationPropertyChanged)); - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty FooterProperty = - DependencyProperty.Register("Footer", typeof(Object), typeof(TaskDialog), - new PropertyMetadata(null, FooterPropertyChanged)); - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty FooterIconProperty = - DependencyProperty.Register("FooterIcon", typeof(ImageSource), typeof(TaskDialog), - new PropertyMetadata(null, FooterIconPropertyChanged)); - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty IconProperty = - DependencyProperty.Register("Icon", typeof(ImageSource), typeof(TaskDialog), - new PropertyMetadata(null, IconPropertyChanged)); - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty InstructionProperty = - DependencyProperty.Register("Instruction", typeof(String), typeof(TaskDialog), - new PropertyMetadata(null, InstructionPropertyChanged)); - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty TitleProperty = - DependencyProperty.Register("Title", typeof(String), typeof(TaskDialog), - new PropertyMetadata(null)); - - /// - /// Identifies the dependency property. - /// - public static readonly DependencyProperty VerificationTextProperty = - DependencyProperty.Register("VerificationText", typeof(String), typeof(TaskDialog), - new PropertyMetadata(null)); - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the TaskDialog class. - /// - public TaskDialog() - { - // Default initialization - buttons = new TaskDialogElementCollection(); - radioButtons = new TaskDialogElementCollection(); - useDefaultIcon = true; - } - - #endregion - - #region Events - - /// - /// Occurs when this is activated. This event coincides with - /// cases where the value of the property changes from False - /// to True. - /// - public event EventHandler Activated { - add { - activatedEventHandler = - (EventHandler)Delegate.Combine(activatedEventHandler, value); - } - remove { - activatedEventHandler = - (EventHandler)Delegate.Remove(activatedEventHandler, value); - } - } - - /// - /// Occurs when this is closed. - /// - public event EventHandler Closed { - add { - closedEventHandler = - (EventHandler)Delegate.Combine(closedEventHandler, value); - } - remove { - closedEventHandler = - (EventHandler)Delegate.Remove(closedEventHandler, value); - } - } - - /// - /// Occurs when the of this changes from - /// Expanded to Collapsed. - /// - public event EventHandler Collapsed { - add { - collapsedEventHandler = - (EventHandler)Delegate.Combine(collapsedEventHandler, value); - } - remove { - collapsedEventHandler = - (EventHandler)Delegate.Remove(collapsedEventHandler, value); - } - } - - /// - /// Occurs when the of this changes from - /// Collapsed to Expanded. - /// - public event EventHandler Expanded { - add { - expandedEventHandler = - (EventHandler)Delegate.Combine(expandedEventHandler, value); - } - remove { - expandedEventHandler = - (EventHandler)Delegate.Remove(expandedEventHandler, value); - } - } - - /// - /// Occurs when this is activated and the F1 key is pressed. - /// - public event EventHandler Help { - add { - helpEventHandler = - (EventHandler)Delegate.Combine(helpEventHandler, value); - } - remove { - helpEventHandler = - (EventHandler)Delegate.Remove(helpEventHandler, value); - } - } - - /// - /// Occurs when this is initialized. This event coincides with - /// cases where the value of the property changes from False - /// to True. - /// - public event EventHandler Initialized { - add { - initializedEventHandler = - (EventHandler)Delegate.Combine(initializedEventHandler, value); - } - remove { - initializedEventHandler = - (EventHandler)Delegate.Remove(initializedEventHandler, value); - } - } - - /// - /// Occurs approximately every 200 milliseconds when this is - /// activated and the property is set to True. - /// - public event EventHandler Timer { - add { - timerEventHandler = - (EventHandler)Delegate.Combine(timerEventHandler, - value); - } - remove { - timerEventHandler = - (EventHandler)Delegate.Remove(timerEventHandler, - value); - } - } - - /// - /// Occurs when the state of the verification checkbox on this - /// changes. This event coincides with cases where the value of the - /// property changes. - /// - public event EventHandler VerificationChanged { - add { - verificationChangedEventHandler = - (EventHandler)Delegate.Combine(verificationChangedEventHandler, value); - } - remove { - verificationChangedEventHandler = - (EventHandler)Delegate.Remove(verificationChangedEventHandler, value); - } - } - - #endregion - - #region Properties - - /// - /// Gets or sets whether this can be closed using Alt-F4, Escape, - /// and the title bar's close button even if no cancel button is specified in either the - /// property or collection. - /// - [DefaultValue(false)] - public Boolean AllowCancellation { - get { return allowCancellation; } - set { - VerifyPropertyWriteAccess("AllowCancellation"); - allowCancellation = value; - } - } - - /// - /// Gets a containing the - /// custom buttons of this . - /// - public TaskDialogElementCollection Buttons { - get { return buttons; } - } - - /// - /// Gets or sets the of the custom buttons of this - /// . - /// - /// - /// This property has no effect on this if no custom buttons are - /// defined. - /// - [DefaultValue(TaskDialogButtonStyle.Normal)] - public TaskDialogButtonStyle ButtonStyle { - get { return buttonStyle; } - set { - VerifyPropertyWriteAccess("ButtonStyle"); - buttonStyle = value; - } - } - - /// - /// Gets or sets whether this can be minimized. - /// - [DefaultValue(false)] - public Boolean CanMinimize { - get { return canMinimize; } - set { - VerifyPropertyWriteAccess("CanMinimize"); - canMinimize = value; - } - } - - /// - /// Gets or sets the text that is displayed next to the expando when the - /// if this is Collapsed. - /// - /// - /// The value of this property has no effect on this if the - /// property has no content. - /// - public String CollapsedControlText { - get { return GetValue(CollapsedControlTextProperty) as String; } - set { - VerifyPropertyWriteAccess("CollapsedControlText"); - SetValue(CollapsedControlTextProperty, value); ; - } - } - - /// - /// Gets or sets the that are visible on this - /// . - /// - [DefaultValue(TaskDialogButtons.None)] - public TaskDialogButtons CommonButtons { - get { return commonButtons; } - set { - VerifyPropertyWriteAccess("CommonButtons"); - commonButtons = value; - } - } - - /// - /// Gets or sets the content to display on this . - /// - public Object Content { - get { return GetValue(ContentProperty); } - set { SetValue(ContentProperty, value); } - } - - /// - /// Gets or sets the default button of this . - /// - /// - /// The value of this property represents either an index into the - /// collection, or a enumeration value of a common button - /// defined in the property. - /// property. - /// - [DefaultValue(0)] - public Int32 DefaultButton - { - get { return defaultButton; } - set { - // Verify state - VerifyPropertyWriteAccess("DefaultButton"); - - // Verify value - if (value < 0) { - throw new ArgumentOutOfRangeException("value"); - } - - defaultButton = value; - } - } - - /// - /// Gets or sets the default icon of this . - /// - /// - /// The value of this property has no effect on this if the - /// property is set to False. - /// - [DefaultValue(TaskDialogIcon.None)] - public TaskDialogIcon DefaultIcon { - get { return defaultIcon; } - set { defaultIcon = value; } - } - - /// - /// Gets or sets the default radio button of this . - /// - /// - /// The value of this property has no effect on this if the - /// collection is empty. - /// - [DefaultValue(0)] - public Int32 DefaultRadioButton { - get { return defaultRadioButton; } - set { - // Verify state - VerifyPropertyWriteAccess("DefaultRadioButton"); - - // Verify value - if (value < -1) { - throw new ArgumentOutOfRangeException("value"); - } - - defaultRadioButton = value; - } - } - - /// - /// Gets or sets the default of this . - /// - [DefaultValue(TaskDialogState.Collapsed)] - public TaskDialogState DefaultState - { - get { return defaultState; } - set { - VerifyPropertyWriteAccess("DefaultState"); - defaultState = value; - } - } - - /// - /// Gets or sets whether hyperlink processing is enabled for the , - /// , and properties. - /// - [DefaultValue(false)] - public Boolean EnableHyperlinks { - get { return enableHyperlinks; } - set { - VerifyPropertyWriteAccess("EnableHyperlinks"); - enableHyperlinks = value; - } - } - - /// - /// Gets or sets whether the event should be raised when this - /// is activated. - /// - [DefaultValue(false)] - public Boolean EnableTimer { - get { return enableTimer; } - set { - VerifyPropertyWriteAccess("EnableTimer"); - enableTimer = value; - } - } - - /// - /// Gets or sets the text that is displayed next to the expando when the - /// if this is Expanded. - /// - /// - /// The value of this property has no effect on this if the - /// property has no content. - /// - public String ExpandedControlText { - get { return GetValue(ExpandedControlTextProperty) as String; } - set { - VerifyPropertyWriteAccess("ExpandedControlText"); - SetValue(ExpandedControlTextProperty, value); - } - } - - /// - /// Gets or sets the expanded information text for this . - /// - /// - /// The expanded information section will only be visible on this - /// if the value of this property is not null. - /// - public Object ExpandedInformation { - get { return GetValue(ExpandedInformationProperty); } - set { SetValue(ExpandedInformationProperty, value); } - } - - /// - /// Gets or sets whether the text should be placed after - /// the footer of this rather than in the content area. - /// - /// - /// The value of this property has no effect on this if the value - /// of the property is null. - /// - [DefaultValue(false)] - public Boolean ExpandFooter - { - get { return expandFooter; } - set { - VerifyPropertyWriteAccess("ExpandFooter"); - expandFooter = value; - } - } - - /// - /// Gets or sets the footer text of this . - /// - /// - /// The footer will only be visible on this if the value of this - /// property is not null. - /// - public Object Footer { - get { return GetValue(FooterProperty); } - set { SetValue(FooterProperty, value); } - } - - /// - /// Gets or sets the icon that is displyed next to the footer text of this - /// . - /// - /// - /// The value of this property has no effect on this if the value - /// of the property is null. - /// - public ImageSource FooterIcon { - get { return GetValue(FooterIconProperty) as ImageSource; } - set { SetValue(FooterIconProperty, value); } - } + /// + /// Represents a dialog box that can be used to display information and receive simple input + /// from the user. + /// + /// + /// Like a , a task dialog is formatted by the operating system + /// according to properties you set. However, it offers many more features than a message box. + /// + [DefaultProperty("Content")] + [ContentProperty("Content")] + public class TaskDialog : DependencyObject + { + #region Fields + + readonly TaskDialogElementCollection buttons; + readonly TaskDialogElementCollection radioButtons; + + Boolean activated; + Boolean allowCancellation; + TaskDialogButtonStyle buttonStyle; + Boolean canMinimize; + TaskDialogButtons commonButtons; + Int32 defaultButton; + TaskDialogIcon defaultIcon; + Int32 defaultRadioButton; + TaskDialogState defaultState; + Boolean enableHyperlinks; + Boolean enableTimer; + Boolean expanded; + Boolean expandFooter; + IntPtr handle; + Boolean initialized; + TaskDialogProgressBar? progressBar; + Boolean sizeToContent; + Boolean useDefaultIcon; + Boolean verificationChecked; + + // This needs to be a class member so that GC doesn't free it prematurely. + NativeMethods.TaskDialogCallbackProc? callback; + + IconHandle? iconHandle; + IconHandle? footerIconHandle; + + EventHandler? activatedEventHandler; + EventHandler? closedEventHandler; + EventHandler? collapsedEventHandler; + EventHandler? expandedEventHandler; + EventHandler? helpEventHandler; + EventHandler? initializedEventHandler; + EventHandler? timerEventHandler; + EventHandler? verificationChangedEventHandler; + + #endregion + + #region Fields: Dependency Properties + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty CollapsedControlTextProperty = + DependencyProperty.Register("CollapsedControlText", typeof(String), typeof(TaskDialog), + new PropertyMetadata(null)); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty ContentProperty = + DependencyProperty.Register("Content", typeof(Object), typeof(TaskDialog), + new PropertyMetadata(null, ContentPropertyChanged)); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty ExpandedControlTextProperty = + DependencyProperty.Register("ExpandedControlText", typeof(String), typeof(TaskDialog), + new PropertyMetadata(null)); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty ExpandedInformationProperty = + DependencyProperty.Register("ExpandedInformation", typeof(Object), typeof(TaskDialog), + new PropertyMetadata(null, ExpandedInformationPropertyChanged)); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty FooterProperty = + DependencyProperty.Register("Footer", typeof(Object), typeof(TaskDialog), + new PropertyMetadata(null, FooterPropertyChanged)); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty FooterIconProperty = + DependencyProperty.Register("FooterIcon", typeof(ImageSource), typeof(TaskDialog), + new PropertyMetadata(null, FooterIconPropertyChanged)); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty IconProperty = + DependencyProperty.Register("Icon", typeof(ImageSource), typeof(TaskDialog), + new PropertyMetadata(null, IconPropertyChanged)); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty InstructionProperty = + DependencyProperty.Register("Instruction", typeof(String), typeof(TaskDialog), + new PropertyMetadata(null, InstructionPropertyChanged)); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty TitleProperty = + DependencyProperty.Register("Title", typeof(String), typeof(TaskDialog), + new PropertyMetadata(null)); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty VerificationTextProperty = + DependencyProperty.Register("VerificationText", typeof(String), typeof(TaskDialog), + new PropertyMetadata(null)); + + #endregion + + #region Constructors and Destructors + + /// + /// Initializes a new instance of the TaskDialog class. + /// + public TaskDialog() + { + // Default initialization + buttons = new TaskDialogElementCollection(); + radioButtons = new TaskDialogElementCollection(); + useDefaultIcon = true; + } + + /// + /// Cleans up the TaskDialog class. + /// + ~TaskDialog() + { + callback = null; + } + + #endregion + + #region Events + + /// + /// Occurs when this is activated. This event coincides with + /// cases where the value of the property changes from False + /// to True. + /// + public event EventHandler Activated + { + add + { + activatedEventHandler = + (EventHandler)Delegate.Combine(activatedEventHandler, value); + } + remove + { + activatedEventHandler = + (EventHandler)Delegate.Remove(activatedEventHandler, value); + } + } + + /// + /// Occurs when this is closed. + /// + public event EventHandler Closed + { + add + { + closedEventHandler = + (EventHandler)Delegate.Combine(closedEventHandler, value); + } + remove + { + closedEventHandler = + (EventHandler)Delegate.Remove(closedEventHandler, value); + } + } + + /// + /// Occurs when the of this changes from + /// Expanded to Collapsed. + /// + public event EventHandler Collapsed + { + add + { + collapsedEventHandler = + (EventHandler)Delegate.Combine(collapsedEventHandler, value); + } + remove + { + collapsedEventHandler = + (EventHandler)Delegate.Remove(collapsedEventHandler, value); + } + } + + /// + /// Occurs when the of this changes from + /// Collapsed to Expanded. + /// + public event EventHandler Expanded + { + add + { + expandedEventHandler = + (EventHandler)Delegate.Combine(expandedEventHandler, value); + } + remove + { + expandedEventHandler = + (EventHandler)Delegate.Remove(expandedEventHandler, value); + } + } + + /// + /// Occurs when this is activated and the F1 key is pressed. + /// + public event EventHandler Help + { + add + { + helpEventHandler = + (EventHandler)Delegate.Combine(helpEventHandler, value); + } + remove + { + helpEventHandler = + (EventHandler)Delegate.Remove(helpEventHandler, value); + } + } + + /// + /// Occurs when this is initialized. This event coincides with + /// cases where the value of the property changes from False + /// to True. + /// + public event EventHandler Initialized + { + add + { + initializedEventHandler = + (EventHandler)Delegate.Combine(initializedEventHandler, value); + } + remove + { + initializedEventHandler = + (EventHandler)Delegate.Remove(initializedEventHandler, value); + } + } + + /// + /// Occurs approximately every 200 milliseconds when this is + /// activated and the property is set to True. + /// + public event EventHandler Timer + { + add + { + timerEventHandler = + (EventHandler)Delegate.Combine(timerEventHandler, + value); + } + remove + { + timerEventHandler = + (EventHandler)Delegate.Remove(timerEventHandler, + value); + } + } + + /// + /// Occurs when the state of the verification checkbox on this + /// changes. This event coincides with cases where the value of the + /// property changes. + /// + public event EventHandler VerificationChanged + { + add + { + verificationChangedEventHandler = + (EventHandler)Delegate.Combine(verificationChangedEventHandler, value); + } + remove + { + verificationChangedEventHandler = + (EventHandler)Delegate.Remove(verificationChangedEventHandler, value); + } + } + + #endregion + + #region Properties + + /// + /// Gets or sets whether this can be closed using Alt-F4, Escape, + /// and the title bar's close button even if no cancel button is specified in either the + /// property or collection. + /// + [DefaultValue(false)] + public Boolean AllowCancellation + { + get { return allowCancellation; } + set + { + VerifyPropertyWriteAccess("AllowCancellation"); + allowCancellation = value; + } + } + + /// + /// Gets a containing the + /// custom buttons of this . + /// + public TaskDialogElementCollection Buttons + { + get { return buttons; } + } + + /// + /// Gets or sets the of the custom buttons of this + /// . + /// + /// + /// This property has no effect on this if no custom buttons are + /// defined. + /// + [DefaultValue(TaskDialogButtonStyle.Normal)] + public TaskDialogButtonStyle ButtonStyle + { + get { return buttonStyle; } + set + { + VerifyPropertyWriteAccess("ButtonStyle"); + buttonStyle = value; + } + } + + /// + /// Gets or sets whether this can be minimized. + /// + [DefaultValue(false)] + public Boolean CanMinimize + { + get { return canMinimize; } + set + { + VerifyPropertyWriteAccess("CanMinimize"); + canMinimize = value; + } + } + + /// + /// Gets or sets the text that is displayed next to the expando when the + /// if this is Collapsed. + /// + /// + /// The value of this property has no effect on this if the + /// property has no content. + /// + public string? CollapsedControlText + { + get { return GetValue(CollapsedControlTextProperty) as string; } + set + { + VerifyPropertyWriteAccess("CollapsedControlText"); + SetValue(CollapsedControlTextProperty, value); ; + } + } + + /// + /// Gets or sets the that are visible on this + /// . + /// + [DefaultValue(TaskDialogButtons.None)] + public TaskDialogButtons CommonButtons + { + get { return commonButtons; } + set + { + VerifyPropertyWriteAccess("CommonButtons"); + commonButtons = value; + } + } + + /// + /// Gets or sets the content to display on this . + /// + public object? Content + { + get { return GetValue(ContentProperty); } + set { SetValue(ContentProperty, value); } + } + + /// + /// Gets or sets the default button of this . + /// + /// + /// The value of this property represents either an index into the + /// collection, or a enumeration value of a common button + /// defined in the property. + /// property. + /// + [DefaultValue(0)] + public Int32 DefaultButton + { + get { return defaultButton; } + set + { + // Verify state + VerifyPropertyWriteAccess("DefaultButton"); + + // Verify value + if (value < 0) + { + throw new ArgumentOutOfRangeException("value"); + } + + defaultButton = value; + } + } + + /// + /// Gets or sets the default icon of this . + /// + /// + /// The value of this property has no effect on this if the + /// property is set to False. + /// + [DefaultValue(TaskDialogIcon.None)] + public TaskDialogIcon DefaultIcon + { + get { return defaultIcon; } + set { defaultIcon = value; } + } + + /// + /// Gets or sets the default radio button of this . + /// + /// + /// The value of this property has no effect on this if the + /// collection is empty. + /// + [DefaultValue(0)] + public Int32 DefaultRadioButton + { + get { return defaultRadioButton; } + set + { + // Verify state + VerifyPropertyWriteAccess("DefaultRadioButton"); + + // Verify value + if (value < -1) + { + throw new ArgumentOutOfRangeException("value"); + } + + defaultRadioButton = value; + } + } + + /// + /// Gets or sets the default of this . + /// + [DefaultValue(TaskDialogState.Collapsed)] + public TaskDialogState DefaultState + { + get { return defaultState; } + set + { + VerifyPropertyWriteAccess("DefaultState"); + defaultState = value; + } + } + + /// + /// Gets or sets whether hyperlink processing is enabled for the , + /// , and properties. + /// + [DefaultValue(false)] + public Boolean EnableHyperlinks + { + get { return enableHyperlinks; } + set + { + VerifyPropertyWriteAccess("EnableHyperlinks"); + enableHyperlinks = value; + } + } + + /// + /// Gets or sets whether the event should be raised when this + /// is activated. + /// + [DefaultValue(false)] + public Boolean EnableTimer + { + get { return enableTimer; } + set + { + VerifyPropertyWriteAccess("EnableTimer"); + enableTimer = value; + } + } + + /// + /// Gets or sets the text that is displayed next to the expando when the + /// if this is Expanded. + /// + /// + /// The value of this property has no effect on this if the + /// property has no content. + /// + public string? ExpandedControlText + { + get { return GetValue(ExpandedControlTextProperty) as string; } + set + { + VerifyPropertyWriteAccess("ExpandedControlText"); + SetValue(ExpandedControlTextProperty, value); + } + } + + /// + /// Gets or sets the expanded information text for this . + /// + /// + /// The expanded information section will only be visible on this + /// if the value of this property is not null. + /// + public Object ExpandedInformation + { + get { return GetValue(ExpandedInformationProperty); } + set { SetValue(ExpandedInformationProperty, value); } + } + + /// + /// Gets or sets whether the text should be placed after + /// the footer of this rather than in the content area. + /// + /// + /// The value of this property has no effect on this if the value + /// of the property is null. + /// + [DefaultValue(false)] + public Boolean ExpandFooter + { + get { return expandFooter; } + set + { + VerifyPropertyWriteAccess("ExpandFooter"); + expandFooter = value; + } + } + + /// + /// Gets or sets the footer text of this . + /// + /// + /// The footer will only be visible on this if the value of this + /// property is not null. + /// + public Object Footer + { + get { return GetValue(FooterProperty); } + set { SetValue(FooterProperty, value); } + } + + /// + /// Gets or sets the icon that is displyed next to the footer text of this + /// . + /// + /// + /// The value of this property has no effect on this if the value + /// of the property is null. + /// + public ImageSource? FooterIcon + { + get { return GetValue(FooterIconProperty) as ImageSource; } + set { SetValue(FooterIconProperty, value); } + } /// /// Gets the native handle of this . /// - public IntPtr Handle { - get { return handle; } - private set { handle = value; } - } - - /// - /// Determines whether this has a progress bar. - /// - public Boolean HasProgressBar { - get { return progressBar != null; } - } - - /// - /// Gets or sets the icon of this . - /// - /// - /// The value of this property has no effect on this if the - /// property is set to True. - /// - public ImageSource Icon { - get { return GetValue(IconProperty) as ImageSource; } - set { SetValue(IconProperty, value); } - } - - /// - /// Gets or sets the instruction text of this . - /// - public String Instruction { - get { return GetValue(InstructionProperty) as String; } - set { SetValue(InstructionProperty, value); } - } - - /// - /// Determines whether this is activated. - /// - public Boolean IsActivated { - get { return activated; } - private set { activated = value; } - } - - /// - /// Determines whether this is expanded. - /// - public Boolean IsExpanded { - get { return expanded; } - private set { expanded = value; } - } - - /// - /// Determines whether this is initialized. - /// - public Boolean IsInitialized { - get { return initialized; } - private set { initialized = value; } - } - - /// - /// Determines whether the verficiation checkbox of this is - /// checked. - /// - /// - /// The value of this property has no effect on this if the value - /// of the property is null. - /// - [DefaultValue(false)] - public Boolean IsVerificationChecked { - get { return verificationChecked; } - set { - VerifyPropertyWriteAccess("VerificationChecked"); - verificationChecked = value; - } - } - - internal Window Owner { - get { return owner; } - set { owner = value; } - } - - /// - /// Gets or sets the of this . - /// - public TaskDialogProgressBar ProgressBar { - get { return progressBar; } - set { - VerifyPropertyWriteAccess("ProgressBar"); - progressBar = value; - - if (progressBar != null) { - progressBar.Owner = this; - } - } - } - - /// - /// Gets a that - /// contains the custom radio buttons of this . - /// - public TaskDialogElementCollection RadioButtons { - get { return radioButtons; } - } - - /// - /// Gets or sets whether the size of this is determined by its - /// contents. - /// - [DefaultValue(false)] - public Boolean SizeToContent { - get { return sizeToContent; } - set { - VerifyPropertyWriteAccess("SizeToContent"); - sizeToContent = value; - } - } - - /// - /// Determines whether this is collapsed or expanded. - /// - public TaskDialogState State { - get { return IsExpanded ? TaskDialogState.Expanded : TaskDialogState.Collapsed; } - } - - /// - /// Gets or sets the title text of this . - /// - public String Title { - get { return GetValue(TitleProperty) as String; } - set { SetValue(TitleProperty, value); } - } - - /// - /// Gets or sets whether this should use the icon specified in the - /// property as its icon. - /// - [DefaultValue(true)] - public Boolean UseDefaultIcon { - get { return useDefaultIcon; } - set { useDefaultIcon = value; } - } - - /// - /// Gets or sets the text that is displayed next to the verification checkbox on this - /// . - /// - /// - /// The verification checkbox will only be visible on this if the - /// value of this property is not null. - /// - public String VerificationText { - get { return GetValue(VerificationTextProperty) as String; } - set { SetValue(VerificationTextProperty, value); } - } - - #endregion - - #region Methods - - /// - /// Displays this and returns when it is closed. - /// - /// A value that represents result data. - public TaskDialogResult Show() - { - // Validate state - if (IsInitialized) { - throw new InvalidOperationException("The current instance is already initialized."); - } - - // Check if Common Controls version 6 is present (declared via manifest) - NativeMethods.DLLVERSIONINFO dvi = new NativeMethods.DLLVERSIONINFO(); - dvi.cbSize = (UInt32)Marshal.SizeOf(typeof(NativeMethods.DLLVERSIONINFO)); - - // Call DllGetVersion on common controls - Int32 hr = NativeMethods.DllGetVersion(ref dvi); - - // Handle method call exceptions - if (hr != NativeMethods.S_OK) { - Marshal.ThrowExceptionForHR(hr); - } - - // Check for major version 6 or greater - if (!(dvi.dwMajorVersion >= 6)) { - throw new NotSupportedException("Missing application manifest dependency "+ - "declaration for Microsoft Common Controls " + - "version 6."); - } - - // Initialize task dialog configuration - NativeMethods.TASKDIALOGCONFIG taskDialogConfig = new NativeMethods.TASKDIALOGCONFIG(); - taskDialogConfig.cbSize = (UInt32)Marshal.SizeOf(typeof(NativeMethods.TASKDIALOGCONFIG)); - taskDialogConfig.hInstance = NativeMethods.GetModuleHandle(); - taskDialogConfig.pfCallback = TaskDialogProc; - - Debug.Assert(taskDialogConfig.hInstance != IntPtr.Zero); - - // Check if the task dialog has an owner window - if (Owner != null) { - WindowInteropHelper wih = new WindowInteropHelper(Owner); - - if (wih.Handle == IntPtr.Zero) { - // Error: The owner window has either not been initialized or is closed. - throw new InvalidOperationException("The owner window has either not been " + - "initialized or is closed."); - } - - taskDialogConfig.hWndParent = wih.Handle; - } - - // Initialize flags - if (AllowCancellation) { - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION; - } - - switch (ButtonStyle) { - case TaskDialogButtonStyle.CommandLinks: - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS; - break; - case TaskDialogButtonStyle.CommandLinksNoIcon: - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS_NO_ICON; - break; - } - - if (CanMinimize) { - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_CAN_BE_MINIMIZED; - } - - if (DefaultRadioButton == -1) { - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_NO_DEFAULT_RADIO_BUTTON; - } - - switch (DefaultState) { - case TaskDialogState.Expanded: - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_EXPANDED_BY_DEFAULT; - break; - } - - if (EnableHyperlinks) { - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_ENABLE_HYPERLINKS; - } - - if (EnableTimer) { - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_CALLBACK_TIMER; - } - - if (ExpandFooter) { - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_EXPAND_FOOTER_AREA; - } - - if (HasProgressBar) { - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_SHOW_PROGRESS_BAR; - - switch (ProgressBar.Style) { - case TaskDialogProgressBarStyle.Marquee: - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_SHOW_MARQUEE_PROGRESS_BAR; - break; - } - } - - if (IsVerificationChecked) { - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED; - } - - if (SizeToContent) { - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_SIZE_TO_CONTENT; - } - - // Prepare formatted elements, if necessary - TaskDialogText taskDialogText; - - if (Content is TaskDialogText) { - taskDialogText = (TaskDialogText)Content; - foreach (TaskDialogTextElement element in taskDialogText.Contents) { - element.Owner = this; - } - } - - if (ExpandedInformation is TaskDialogText) { - taskDialogText = (TaskDialogText)ExpandedInformation; - foreach (TaskDialogTextElement element in taskDialogText.Contents) { - element.Owner = this; - } - } - - if (Footer is TaskDialogText) { - taskDialogText = (TaskDialogText)Footer; - foreach (TaskDialogTextElement element in taskDialogText.Contents) { - element.Owner = this; - } - } - - // Initialize strings - taskDialogConfig.pszWindowTitle = Title; - taskDialogConfig.pszMainInstruction = Instruction; - - if (Content != null) { - taskDialogConfig.pszContent = Content.ToString(); - } - - if (ExpandedInformation != null) { - taskDialogConfig.pszExpandedInformation = ExpandedInformation.ToString(); - } - - if (Footer != null) { - taskDialogConfig.pszFooter = Footer.ToString(); - } - - taskDialogConfig.pszCollapsedControlText = CollapsedControlText; - taskDialogConfig.pszExpandedControlText = ExpandedControlText; - taskDialogConfig.pszVerificationText = VerificationText; - - // Initialize common buttons - taskDialogConfig.dwCommonButtons = - (NativeMethods.TASKDIALOG_COMMON_BUTTON_FLAGS)CommonButtons; - - // Initialize icons - if (UseDefaultIcon) { - taskDialogConfig.hMainIcon = (IntPtr)(UInt16)DefaultIcon; - } else if (Icon != null) { - if (iconHandle != null) { - if (!iconHandle.IsClosed) { - iconHandle.Close(); - } - } - iconHandle = IconHandle.Create(Icon); - taskDialogConfig.hMainIcon = iconHandle.Value; - taskDialogConfig.dwFlags |= - NativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_MAIN; - } - - if (FooterIcon != null) { - if (footerIconHandle != null) { - if (!footerIconHandle.IsClosed) { - footerIconHandle.Close(); - } - } - footerIconHandle = IconHandle.Create(FooterIcon); - taskDialogConfig.hFooterIcon = footerIconHandle.Value; - } - - taskDialogConfig.dwFlags |= NativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_FOOTER; - - // Initialize buttons - IntPtr buttonPtr = IntPtr.Zero; - - if (Buttons.Count != 0) { - // Allocate unmanaged memory for the button array - buttonPtr = Marshal.AllocHGlobal( - Marshal.SizeOf(typeof(NativeMethods.TASKDIALOG_BUTTON)) * Buttons.Count); - - IntPtr offset = buttonPtr; - Int32 buttonID = 16; // Start with 16 to avoid collision with common buttons - - // Copy radio button data from managed list to unmanaged button array - foreach (TaskDialogButton button in Buttons) { - // Set owner - button.Owner = this; - - // Create and initialize native wrapper structure - NativeMethods.TASKDIALOG_BUTTON btn = new NativeMethods.TASKDIALOG_BUTTON(); - btn.nButtonID = buttonID; - btn.pszButtonText = button.ToString(); - - // Marshal to unmanaged memory - Marshal.StructureToPtr(btn, offset, false); - - offset = (IntPtr)((Int64)offset + Marshal.SizeOf(btn)); - buttonID++; - } - - // Set button count and assign pointer to unmanaged button array - taskDialogConfig.cButtons = (UInt32)Buttons.Count; - taskDialogConfig.pButtons = buttonPtr; - } - - taskDialogConfig.nDefaultButton = DefaultButton; - - // Initialize radio buttons - IntPtr radioButtonPtr = IntPtr.Zero; - - if (RadioButtons.Count != 0) { - // Allocate unmanaged memory for the radio button array - radioButtonPtr = Marshal.AllocHGlobal( - Marshal.SizeOf(typeof(NativeMethods.TASKDIALOG_BUTTON)) * RadioButtons.Count); - - IntPtr offset = radioButtonPtr; - Int32 radioButtonID = 0; - - // Copy radio button data from managed list to unmanaged button array - foreach (TaskDialogRadioButton radioButton in RadioButtons) { - // Set owner - radioButton.Owner = this; - - // Create and initialize native wrapper structure - NativeMethods.TASKDIALOG_BUTTON btn = new NativeMethods.TASKDIALOG_BUTTON(); - btn.nButtonID = radioButtonID; - btn.pszButtonText = radioButton.Title; - - // Marshal to unmanaged memory - Marshal.StructureToPtr(btn, offset, false); - - // Adjust offset and radio button ID - offset = (IntPtr)((Int64)offset + Marshal.SizeOf(btn)); - radioButtonID++; - } - - // Set radio button count and assign pointer to unmanaged radio button array - taskDialogConfig.cRadioButtons = (UInt32)RadioButtons.Count; - taskDialogConfig.pRadioButtons = radioButtonPtr; - } - - taskDialogConfig.nDefaultRadioButton = DefaultRadioButton; - - // Present task dialog - Int32 selectedButton; - Int32 selectedRadioButton; - Boolean verificationChecked; - - hr = NativeMethods.TaskDialogIndirect(taskDialogConfig, - out selectedButton, out selectedRadioButton, - out verificationChecked); - try { - // Check HRESULT for errors - if (hr != NativeMethods.S_OK) { - Marshal.ThrowExceptionForHR(hr); - } - } finally { - // Clean up resources - if (radioButtonPtr != IntPtr.Zero) { - Marshal.FreeHGlobal(radioButtonPtr); - } - - if (buttonPtr != IntPtr.Zero) { - Marshal.FreeHGlobal(buttonPtr); - } - - if (footerIconHandle != null) { - if (!footerIconHandle.IsClosed) { - footerIconHandle.Close(); - } - } - - if (iconHandle != null) { - if (!iconHandle.IsClosed) { - iconHandle.Close(); - } - } - } - - return new TaskDialogResult(selectedButton, selectedRadioButton, verificationChecked); - } - - /// - /// Displays this in front of the specified window and returns - /// when it is closed. - /// - /// A that represents the owner of this task - /// dialog. - /// A value that represents result data. - public TaskDialogResult ShowModal(Window owner) - { - // Validate argument - if (owner == null) { - throw new ArgumentNullException("owner"); - } - - // Set owner and show the task dialog - Owner = owner; - return Show(); - } - - #endregion - - #region Methods: Implementation - - void InitializeElements() - { - // Initialize buttons - foreach (TaskDialogButton button in Buttons) { - if (!button.IsEnabled) { - button.SetButtonEnabled(button.IsEnabled); - } - if (button.ElevationRequired) { - button.SetElevationRequired(button.ElevationRequired); - } - } - - // Initialize radio buttons - Int32 radioButtonID = 0; - - foreach (TaskDialogRadioButton radioButton in RadioButtons) { - if (!radioButton.IsEnabled) { - radioButton.SetButtonEnabled(radioButton.IsEnabled); - } - if (radioButtonID == DefaultRadioButton) { - radioButton.IsChecked = true; - } - radioButtonID++; - } - - // Initialize progress bar - if (HasProgressBar) { - ProgressBar.SetProgressBarStyle(ProgressBar.Style); - - switch (ProgressBar.Style) { - case TaskDialogProgressBarStyle.Normal: - ProgressBar.SetProgressBarRange(ProgressBar.Minimum, ProgressBar.Maximum); - ProgressBar.SetProgressBarValue(ProgressBar.Value); - ProgressBar.SetProgressBarState(ProgressBar.State); - break; - case TaskDialogProgressBarStyle.Marquee: - ProgressBar.SetProgressBarMarquee(ProgressBar.RunMarquee, - ProgressBar.MarqueeInterval); - break; - } - } - } - - void SetElementText(NativeMethods.TASKDIALOG_ELEMENTS element, String text) - { - // Allocate unmanaged string - IntPtr stringPtr = Marshal.StringToHGlobalUni(text); - - // Send TDM_SET_ELEMENT_TEXT message to set the element text - NativeMethods.SendMessage( - Handle, (UInt32)NativeMethods.TASKDIALOG_MESSAGES.TDM_SET_ELEMENT_TEXT, - new UIntPtr((UInt32)element), stringPtr); - - // Free resources - Marshal.FreeHGlobal(stringPtr); - } - - void UpdateIcon(NativeMethods.TASKDIALOG_ICON_ELEMENTS iconElement, ImageSource imageSource) - { - IconHandle newHandle = IconHandle.Invalid; - - // Create replacement handle first - switch (iconElement) { - case NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_MAIN: - newHandle = IconHandle.Create(imageSource); - break; - case NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_FOOTER: - newHandle = IconHandle.Create(imageSource); - break; - } - - // Send TDM_UPDATE_ICON message to update the icon - NativeMethods.SendMessage( - Handle, (UInt32)NativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ICON, - new UIntPtr((UInt32)iconElement), newHandle.Value); - - // Release previous icon handle and replace with new handle - switch (iconElement) { - case NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_MAIN: - iconHandle.Close(); - iconHandle = newHandle; - break; - case NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_FOOTER: - footerIconHandle.Close(); - footerIconHandle = newHandle; - break; - } - } - - void VerifyPropertyWriteAccess(String propertyName) - { - // Allow property write access only on inactive state - if (IsInitialized) { - throw new InvalidOperationException( - String.Format("The property '{0}' cannot be set when the current instance is " + - "in an initialized state.", propertyName)); - } - } - - #endregion - - #region Methods: Dependency Property Callbacks - - static void ContentPropertyChanged(DependencyObject source, - DependencyPropertyChangedEventArgs e) - { - TaskDialog taskDialog = source as TaskDialog; - - if (taskDialog != null) { - if (taskDialog.IsActivated) { - taskDialog.SetElementText( - NativeMethods.TASKDIALOG_ELEMENTS.TDE_CONTENT, - (String)e.NewValue); - } - } - } - - static void ExpandedInformationPropertyChanged(DependencyObject source, - DependencyPropertyChangedEventArgs e) - { - TaskDialog taskDialog = source as TaskDialog; - - if (taskDialog != null) { - if (taskDialog.IsActivated) { - taskDialog.SetElementText( - NativeMethods.TASKDIALOG_ELEMENTS.TDE_EXPANDED_INFORMATION, - (String)e.NewValue); - } - } - } - - static void FooterPropertyChanged(DependencyObject source, - DependencyPropertyChangedEventArgs e) - { - TaskDialog taskDialog = source as TaskDialog; - - if (taskDialog != null) { - if (taskDialog.IsActivated) { - taskDialog.SetElementText( - NativeMethods.TASKDIALOG_ELEMENTS.TDE_FOOTER, - (String)e.NewValue); - } - } - } - - static void FooterIconPropertyChanged(DependencyObject source, - DependencyPropertyChangedEventArgs e) - { - TaskDialog taskDialog = source as TaskDialog; - - if (taskDialog != null) { - if (taskDialog.IsActivated) { - taskDialog.UpdateIcon( - NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_FOOTER, - (ImageSource)e.NewValue); - } - } - } - - static void IconPropertyChanged(DependencyObject source, - DependencyPropertyChangedEventArgs e) - { - TaskDialog taskDialog = source as TaskDialog; - - if (taskDialog != null) { - if (taskDialog.IsActivated) { - if (!taskDialog.UseDefaultIcon) { - taskDialog.UpdateIcon( - NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_MAIN, - (ImageSource)e.NewValue); - } - } - } - } - - static void InstructionPropertyChanged(DependencyObject source, - DependencyPropertyChangedEventArgs e) - { - TaskDialog taskDialog = source as TaskDialog; - - if (taskDialog != null) { - if (taskDialog.IsActivated) { - taskDialog.SetElementText( - NativeMethods.TASKDIALOG_ELEMENTS.TDE_MAIN_INSTRUCTION, - (String)e.NewValue); - } - } - } - - #endregion - - #region Methods: Event Handler - - /// - /// Raises the event. - /// - /// An object that contains the event data. - protected virtual void OnActivated(EventArgs e) - { - EventHandler handler = activatedEventHandler; - - if (handler != null) { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// An object that contains the event data. - protected virtual void OnClosed(EventArgs e) - { - EventHandler handler = closedEventHandler; - - if (handler != null) { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// An object that contains the event data. - protected virtual void OnCollapsed(EventArgs e) - { - EventHandler handler = collapsedEventHandler; - - if (handler != null) { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// An object that contains the event data. - protected virtual void OnExpanded(EventArgs e) - { - EventHandler handler = expandedEventHandler; - - if (handler != null) { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// An object that contains the event data. - protected virtual void OnHelp(EventArgs e) - { - EventHandler handler = helpEventHandler; - - if (handler != null) { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// An object that contains the event data. - protected virtual void OnInitialized(EventArgs e) - { - EventHandler handler = initializedEventHandler; - - if (handler != null) { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// An object that contains the - /// timer event data. - protected virtual void OnTimer(TaskDialogTimerEventArgs e) - { - EventHandler handler = timerEventHandler; - - if (handler != null) { - handler(this, e); - } - } - - /// - /// Raises the event. - /// - /// An object that contains the event data. - protected virtual void OnVerificationChanged(EventArgs e) - { - EventHandler handler = verificationChangedEventHandler; - - if (handler != null) { - handler(this, e); - } - } - - #endregion - - #region Methods: Static - - /// - /// Displays a . - /// - /// A that specifies the instruction text - /// to display. - /// A value that specifies which common button - /// was selected by the user. - public static TaskDialogResult Show(String instruction) - { - return Show(instruction, null, null, TaskDialogButtons.None, TaskDialogIcon.None); - } - - /// - /// Displays a . - /// - /// A that specifies the instruction text - /// to display. - /// A that specifies the content text to - /// display. - /// A value that specifies which common button - /// was selected by the user. - public static TaskDialogResult Show(String instruction, String content) - { - return Show(instruction, content, null, TaskDialogButtons.None, TaskDialogIcon.None); - } - - /// - /// Displays a . - /// - /// A that specifies the instruction text - /// to display. - /// A that specifies the content text to - /// display. - /// A that specifies the title bar text of the - /// task dialog. - /// A value that specifies which common button - /// was selected by the user. - public static TaskDialogResult Show(String instruction, String content, String title) - { - return Show(instruction, content, title, TaskDialogButtons.None, TaskDialogIcon.None); - } - - /// - /// Displays a . - /// - /// A that specifies the instruction text - /// to display. - /// A that specifies the content text to - /// display. - /// A that specifies the title bar text of the - /// task dialog. - /// A value that specifies which - /// buttons to display. - /// A value that specifies which common button - /// was selected by the user. - public static TaskDialogResult Show(String instruction, String content, String title, - TaskDialogButtons buttons) - { - return Show(instruction, content, title, buttons, TaskDialogIcon.None); - } - - /// - /// Displays a . - /// - /// A that specifies the instruction text - /// to display. - /// A that specifies the content text to - /// display. - /// A that specifies the title bar text of the - /// task dialog. - /// A value that specifies which - /// buttons to display. - /// A value that specifies the icon to - /// display. - /// A value that specifies which common button - /// was selected by the user. - public static TaskDialogResult Show(String instruction, String content, String title, - TaskDialogButtons buttons, TaskDialogIcon icon) - { - // Initialize task dialog instance - TaskDialog taskDialog = new TaskDialog(); - taskDialog.Title = title; - taskDialog.Instruction = instruction; - taskDialog.Content = content; - taskDialog.CommonButtons = buttons; - taskDialog.DefaultIcon = icon; - - // Show instance and return result - return taskDialog.Show(); - } - - /// - /// Displays a in front of the specified window. - /// - /// A that represents the owner window of the - /// task dialog. - /// A that specifies the instruction text - /// to display. - /// A value that specifies which common button - /// was selected by the user. - public static TaskDialogResult ShowModal(Window owner, String instruction) - { - return ShowModal(owner, instruction, null, null, TaskDialogButtons.None, - TaskDialogIcon.None); - } - - /// - /// Displays a in front of the specified window. - /// - /// A that represents the owner window of the - /// task dialog. - /// A that specifies the instruction text - /// to display. - /// A that specifies the content text to - /// display. - /// A value that specifies which common button - /// was selected by the user. - public static TaskDialogResult ShowModal(Window owner, String instruction, String content) - { - return ShowModal(owner, instruction, content, null, TaskDialogButtons.None, - TaskDialogIcon.None); - } - - /// - /// Displays a in front of the specified window. - /// - /// A that represents the owner window of the - /// task dialog. - /// A that specifies the instruction text - /// to display. - /// A that specifies the content text to - /// display. - /// A that specifies the title bar text of the - /// task dialog. - /// A value that specifies which common button - /// was selected by the user. - public static TaskDialogResult ShowModal(Window owner, String instruction, String content, - String title) - { - return ShowModal(owner, instruction, content, title, TaskDialogButtons.None, - TaskDialogIcon.None); - } - - /// - /// Displays a in front of the specified window. - /// - /// A that represents the owner window of the - /// task dialog. - /// A that specifies the instruction text - /// to display. - /// A that specifies the content text to - /// display. - /// A that specifies the title bar text of the - /// task dialog. - /// A value that specifies which - /// buttons to display. - /// A value that specifies which common button - /// was selected by the user. - public static TaskDialogResult ShowModal(Window owner, String instruction, String content, - String title, TaskDialogButtons buttons) - { - return ShowModal(owner, instruction, content, title, buttons, TaskDialogIcon.None); - } - - /// - /// Displays a in front of the specified window. - /// - /// A that represents the owner window of the - /// task dialog. - /// A that specifies the instruction text - /// to display. - /// A that specifies the content text to - /// display. - /// A that specifies the title bar text of the - /// task dialog. - /// A value that specifies which - /// buttons to display. - /// A value that specifies the icon to - /// display. - /// A value that specifies which common button - /// was selected by the user. - public static TaskDialogResult ShowModal(Window owner, String instruction, String content, - String title, TaskDialogButtons buttons, - TaskDialogIcon icon) - { - // Validate arguments - if (owner == null) { - throw new ArgumentNullException("owner"); - } - - // Initialize task dialog instance - TaskDialog taskDialog = new TaskDialog(); - taskDialog.Title = title; - taskDialog.Instruction = instruction; - taskDialog.Content = content; - taskDialog.CommonButtons = buttons; - taskDialog.DefaultIcon = icon; - - // Show instance and return result - return taskDialog.ShowModal(owner); - } - - #endregion - - #region Methods: TaskDialog Callback Procedure - - Int32 TaskDialogProc(IntPtr hwnd, UInt32 uNotification, UIntPtr wParam, IntPtr lParam, - IntPtr dwRefData) - { - Int32 result = NativeMethods.S_OK; - - // Cast notification value - NativeMethods.TASKDIALOG_NOTIFICATIONS notification = - (NativeMethods.TASKDIALOG_NOTIFICATIONS)uNotification; - - // Handle notification - switch (notification) { - case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_BUTTON_CLICKED: - // Get button ID - Int32 buttonID = (Int32)wParam; - - switch (buttonID) { + public IntPtr Handle + { + get { return handle; } + private set { handle = value; } + } + + /// + /// Determines whether this has a progress bar. + /// + public Boolean HasProgressBar + { + get { return progressBar != null; } + } + + /// + /// Gets or sets the icon of this . + /// + /// + /// The value of this property has no effect on this if the + /// property is set to True. + /// + public ImageSource? Icon + { + get { return GetValue(IconProperty) as ImageSource; } + set { SetValue(IconProperty, value); } + } + + /// + /// Gets or sets the instruction text of this . + /// + public string? Instruction + { + get { return GetValue(InstructionProperty) as string; } + set { SetValue(InstructionProperty, value); } + } + + /// + /// Determines whether this is activated. + /// + public Boolean IsActivated + { + get { return activated; } + private set { activated = value; } + } + + /// + /// Determines whether this is expanded. + /// + public Boolean IsExpanded + { + get { return expanded; } + private set { expanded = value; } + } + + /// + /// Determines whether this is initialized. + /// + public Boolean IsInitialized + { + get { return initialized; } + private set { initialized = value; } + } + + /// + /// Determines whether the verficiation checkbox of this is + /// checked. + /// + /// + /// The value of this property has no effect on this if the value + /// of the property is null. + /// + [DefaultValue(false)] + public Boolean IsVerificationChecked + { + get { return verificationChecked; } + set + { + VerifyPropertyWriteAccess("VerificationChecked"); + verificationChecked = value; + } + } + + internal object? Owner { get; set; } + + /// + /// Gets or sets the of this . + /// + public TaskDialogProgressBar? ProgressBar + { + get { return progressBar; } + set + { + VerifyPropertyWriteAccess("ProgressBar"); + progressBar = value; + + if (progressBar != null) + { + progressBar.Owner = this; + } + } + } + + /// + /// Gets a that + /// contains the custom radio buttons of this . + /// + public TaskDialogElementCollection RadioButtons + { + get { return radioButtons; } + } + + /// + /// Gets or sets whether the size of this is determined by its + /// contents. + /// + [DefaultValue(false)] + public Boolean SizeToContent + { + get { return sizeToContent; } + set + { + VerifyPropertyWriteAccess("SizeToContent"); + sizeToContent = value; + } + } + + /// + /// Determines whether this is collapsed or expanded. + /// + public TaskDialogState State + { + get { return IsExpanded ? TaskDialogState.Expanded : TaskDialogState.Collapsed; } + } + + /// + /// Gets or sets the title text of this . + /// + public string? Title + { + get { return GetValue(TitleProperty) as string; } + set { SetValue(TitleProperty, value); } + } + + /// + /// Gets or sets whether this should use the icon specified in the + /// property as its icon. + /// + [DefaultValue(true)] + public Boolean UseDefaultIcon + { + get { return useDefaultIcon; } + set { useDefaultIcon = value; } + } + + /// + /// Gets or sets the text that is displayed next to the verification checkbox on this + /// . + /// + /// + /// The verification checkbox will only be visible on this if the + /// value of this property is not null. + /// + public string? VerificationText + { + get { return GetValue(VerificationTextProperty) as string; } + set { SetValue(VerificationTextProperty, value); } + } + + #endregion + + #region Methods + + /// + /// Displays this and returns when it is closed. + /// + /// A value that represents result data. + public TaskDialogResult Show() + { + // Validate state + if (IsInitialized) + { + throw new InvalidOperationException("The current instance is already initialized."); + } + + // Check if Common Controls version 6 is present (declared via manifest) + NativeMethods.DLLVERSIONINFO dvi = new NativeMethods.DLLVERSIONINFO(); + dvi.cbSize = (UInt32)Marshal.SizeOf(typeof(NativeMethods.DLLVERSIONINFO)); + + // Call DllGetVersion on common controls + Int32 hr = NativeMethods.DllGetVersion(ref dvi); + + // Handle method call exceptions + if (hr != NativeMethods.S_OK) + { + Marshal.ThrowExceptionForHR(hr); + } + + // Check for major version 6 or greater + if (!(dvi.dwMajorVersion >= 6)) + { + throw new NotSupportedException("Missing application manifest dependency " + + "declaration for Microsoft Common Controls " + + "version 6."); + } + + // Initialize task dialog configuration + NativeMethods.TASKDIALOGCONFIG taskDialogConfig = new NativeMethods.TASKDIALOGCONFIG(); + taskDialogConfig.cbSize = (UInt32)Marshal.SizeOf(typeof(NativeMethods.TASKDIALOGCONFIG)); + taskDialogConfig.hInstance = NativeMethods.GetModuleHandle(); + taskDialogConfig.pfCallback = callback = TaskDialogProc; + + Debug.Assert(taskDialogConfig.hInstance != IntPtr.Zero); + + // Check if the task dialog has an owner window + if (Owner != null) + { + IntPtr handle = IntPtr.Zero; + + switch (this.Owner) + { + // a WPF window + case Window window: + WindowInteropHelper wih = new WindowInteropHelper(window); + handle = wih.Handle; + break; + + // a Win32 form (such as from Windows Forms) + case IntPtr ptr: + handle = ptr; + break; + } + + if (handle == IntPtr.Zero) + { + // Error: The owner window has either not been initialized or is closed. + throw new InvalidOperationException("The owner window has either not been " + + "initialized or is closed."); + } + + taskDialogConfig.hWndParent = handle; + } + + // Initialize flags + if (AllowCancellation) + { + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_ALLOW_DIALOG_CANCELLATION; + } + + switch (ButtonStyle) + { + case TaskDialogButtonStyle.CommandLinks: + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS; + break; + case TaskDialogButtonStyle.CommandLinksNoIcon: + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS_NO_ICON; + break; + } + + if (CanMinimize) + { + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_CAN_BE_MINIMIZED; + } + + if (DefaultRadioButton == -1) + { + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_NO_DEFAULT_RADIO_BUTTON; + } + + switch (DefaultState) + { + case TaskDialogState.Expanded: + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_EXPANDED_BY_DEFAULT; + break; + } + + if (EnableHyperlinks) + { + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_ENABLE_HYPERLINKS; + } + + if (EnableTimer) + { + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_CALLBACK_TIMER; + } + + if (ExpandFooter) + { + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_EXPAND_FOOTER_AREA; + } + + if (HasProgressBar) + { + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_SHOW_PROGRESS_BAR; + + switch (ProgressBar?.Style) + { + case TaskDialogProgressBarStyle.Marquee: + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_SHOW_MARQUEE_PROGRESS_BAR; + break; + } + } + + if (IsVerificationChecked) + { + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_VERIFICATION_FLAG_CHECKED; + } + + if (SizeToContent) + { + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_SIZE_TO_CONTENT; + } + + // Prepare formatted elements, if necessary + TaskDialogText taskDialogText; + + if (Content is TaskDialogText) + { + taskDialogText = (TaskDialogText)Content; + foreach (TaskDialogTextElement element in taskDialogText.Contents) + { + element.Owner = this; + } + } + + if (ExpandedInformation is TaskDialogText) + { + taskDialogText = (TaskDialogText)ExpandedInformation; + foreach (TaskDialogTextElement element in taskDialogText.Contents) + { + element.Owner = this; + } + } + + if (Footer is TaskDialogText) + { + taskDialogText = (TaskDialogText)Footer; + foreach (TaskDialogTextElement element in taskDialogText.Contents) + { + element.Owner = this; + } + } + + // Initialize strings + taskDialogConfig.pszWindowTitle = Title; + taskDialogConfig.pszMainInstruction = Instruction; + + if (Content != null) + { + taskDialogConfig.pszContent = Content.ToString(); + } + + if (ExpandedInformation != null) + { + taskDialogConfig.pszExpandedInformation = ExpandedInformation.ToString(); + } + + if (Footer != null) + { + taskDialogConfig.pszFooter = Footer.ToString(); + } + + taskDialogConfig.pszCollapsedControlText = CollapsedControlText; + taskDialogConfig.pszExpandedControlText = ExpandedControlText; + taskDialogConfig.pszVerificationText = VerificationText; + + // Initialize common buttons + taskDialogConfig.dwCommonButtons = + (NativeMethods.TASKDIALOG_COMMON_BUTTON_FLAGS)CommonButtons; + + // Initialize icons + if (UseDefaultIcon) + { + taskDialogConfig.hMainIcon = (IntPtr)(UInt16)DefaultIcon; + } + else if (Icon != null) + { + if (iconHandle != null) + { + if (!iconHandle.IsClosed) + { + iconHandle.Close(); + } + } + iconHandle = IconHandle.Create(Icon); + taskDialogConfig.hMainIcon = iconHandle.Value; + taskDialogConfig.dwFlags |= + NativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_MAIN; + } + + if (FooterIcon != null) + { + if (footerIconHandle != null) + { + if (!footerIconHandle.IsClosed) + { + footerIconHandle.Close(); + } + } + footerIconHandle = IconHandle.Create(FooterIcon); + taskDialogConfig.hFooterIcon = footerIconHandle.Value; + } + + taskDialogConfig.dwFlags |= NativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_FOOTER; + + // Initialize buttons + IntPtr buttonPtr = IntPtr.Zero; + + if (Buttons.Count != 0) + { + // Allocate unmanaged memory for the button array + buttonPtr = Marshal.AllocHGlobal( + Marshal.SizeOf(typeof(NativeMethods.TASKDIALOG_BUTTON)) * Buttons.Count); + + IntPtr offset = buttonPtr; + Int32 buttonID = 16; // Start with 16 to avoid collision with common buttons + + // Copy radio button data from managed list to unmanaged button array + foreach (TaskDialogButton button in Buttons) + { + // Set owner + button.Owner = this; + + // Create and initialize native wrapper structure + NativeMethods.TASKDIALOG_BUTTON btn = new NativeMethods.TASKDIALOG_BUTTON(); + btn.nButtonID = buttonID; + btn.pszButtonText = button.ToString(); + + // Marshal to unmanaged memory + Marshal.StructureToPtr(btn, offset, false); + + offset = (IntPtr)((Int64)offset + Marshal.SizeOf(btn)); + buttonID++; + } + + // Set button count and assign pointer to unmanaged button array + taskDialogConfig.cButtons = (UInt32)Buttons.Count; + taskDialogConfig.pButtons = buttonPtr; + } + + taskDialogConfig.nDefaultButton = DefaultButton; + + // Initialize radio buttons + IntPtr radioButtonPtr = IntPtr.Zero; + + if (RadioButtons.Count != 0) + { + // Allocate unmanaged memory for the radio button array + radioButtonPtr = Marshal.AllocHGlobal( + Marshal.SizeOf(typeof(NativeMethods.TASKDIALOG_BUTTON)) * RadioButtons.Count); + + IntPtr offset = radioButtonPtr; + Int32 radioButtonID = 0; + + // Copy radio button data from managed list to unmanaged button array + foreach (TaskDialogRadioButton radioButton in RadioButtons) + { + // Set owner + radioButton.Owner = this; + + // Create and initialize native wrapper structure + NativeMethods.TASKDIALOG_BUTTON btn = new NativeMethods.TASKDIALOG_BUTTON(); + btn.nButtonID = radioButtonID; + btn.pszButtonText = radioButton.Title; + + // Marshal to unmanaged memory + Marshal.StructureToPtr(btn, offset, false); + + // Adjust offset and radio button ID + offset = (IntPtr)((Int64)offset + Marshal.SizeOf(btn)); + radioButtonID++; + } + + // Set radio button count and assign pointer to unmanaged radio button array + taskDialogConfig.cRadioButtons = (UInt32)RadioButtons.Count; + taskDialogConfig.pRadioButtons = radioButtonPtr; + } + + taskDialogConfig.nDefaultRadioButton = DefaultRadioButton; + + // Present task dialog + Int32 selectedButton; + Int32 selectedRadioButton; + Boolean verificationChecked; + + hr = NativeMethods.TaskDialogIndirect(taskDialogConfig, + out selectedButton, out selectedRadioButton, + out verificationChecked); + try + { + // Check HRESULT for errors + if (hr != NativeMethods.S_OK) + { + Marshal.ThrowExceptionForHR(hr); + } + } + finally + { + // Clean up resources + if (radioButtonPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(radioButtonPtr); + } + + if (buttonPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(buttonPtr); + } + + if (footerIconHandle != null) + { + if (!footerIconHandle.IsClosed) + { + footerIconHandle.Close(); + } + } + + if (iconHandle != null) + { + if (!iconHandle.IsClosed) + { + iconHandle.Close(); + } + } + } + + return new TaskDialogResult(selectedButton, selectedRadioButton, verificationChecked); + } + + /// + /// Displays this in front of the specified window and returns + /// when it is closed. + /// + /// A or that represents the owner of this task + /// dialog. + /// A value that represents result data. + public TaskDialogResult ShowModal(object owner) + { + // Validate argument + if (owner == null) + { + throw new ArgumentNullException("owner"); + } + + // Set owner and show the task dialog + Owner = owner; + return Show(); + } + + #endregion + + #region Methods: Implementation + + void InitializeElements() + { + // Initialize buttons + foreach (TaskDialogButton button in Buttons) + { + if (!button.IsEnabled) + { + button.SetButtonEnabled(button.IsEnabled); + } + if (button.ElevationRequired) + { + button.SetElevationRequired(button.ElevationRequired); + } + } + + // Initialize radio buttons + Int32 radioButtonID = 0; + + foreach (TaskDialogRadioButton radioButton in RadioButtons) + { + if (!radioButton.IsEnabled) + { + radioButton.SetButtonEnabled(radioButton.IsEnabled); + } + if (radioButtonID == DefaultRadioButton) + { + radioButton.IsChecked = true; + } + radioButtonID++; + } + + // Initialize progress bar + if (HasProgressBar) + { + ProgressBar?.SetProgressBarStyle(ProgressBar.Style); + + switch (ProgressBar?.Style) + { + case TaskDialogProgressBarStyle.Normal: + ProgressBar.SetProgressBarRange(ProgressBar.Minimum, ProgressBar.Maximum); + ProgressBar.SetProgressBarValue(ProgressBar.Value); + ProgressBar.SetProgressBarState(ProgressBar.State); + break; + case TaskDialogProgressBarStyle.Marquee: + ProgressBar.SetProgressBarMarquee(ProgressBar.RunMarquee, + ProgressBar.MarqueeInterval); + break; + } + } + } + + void SetElementText(NativeMethods.TASKDIALOG_ELEMENTS element, String text) + { + // Allocate unmanaged string + IntPtr stringPtr = Marshal.StringToHGlobalUni(text); + + // Send TDM_SET_ELEMENT_TEXT message to set the element text + NativeMethods.SendMessage( + Handle, (UInt32)NativeMethods.TASKDIALOG_MESSAGES.TDM_SET_ELEMENT_TEXT, + new UIntPtr((UInt32)element), stringPtr); + + // Free resources + Marshal.FreeHGlobal(stringPtr); + } + + void UpdateIcon(NativeMethods.TASKDIALOG_ICON_ELEMENTS iconElement, ImageSource imageSource) + { + IconHandle newHandle = IconHandle.Invalid; + + // Create replacement handle first + switch (iconElement) + { + case NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_MAIN: + newHandle = IconHandle.Create(imageSource); + break; + case NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_FOOTER: + newHandle = IconHandle.Create(imageSource); + break; + } + + // Send TDM_UPDATE_ICON message to update the icon + NativeMethods.SendMessage( + Handle, (UInt32)NativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ICON, + new UIntPtr((UInt32)iconElement), newHandle.Value); + + // Release previous icon handle and replace with new handle + switch (iconElement) + { + case NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_MAIN: + iconHandle?.Close(); + iconHandle = newHandle; + break; + case NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_FOOTER: + footerIconHandle?.Close(); + footerIconHandle = newHandle; + break; + } + } + + void VerifyPropertyWriteAccess(String propertyName) + { + // Allow property write access only on inactive state + if (IsInitialized) + { + throw new InvalidOperationException( + String.Format("The property '{0}' cannot be set when the current instance is " + + "in an initialized state.", propertyName)); + } + } + + #endregion + + #region Methods: Dependency Property Callbacks + + static void ContentPropertyChanged(DependencyObject source, + DependencyPropertyChangedEventArgs e) + { + TaskDialog? taskDialog = source as TaskDialog; + + if (taskDialog != null) + { + if (taskDialog.IsActivated) + { + taskDialog.SetElementText( + NativeMethods.TASKDIALOG_ELEMENTS.TDE_CONTENT, + (String)e.NewValue); + } + } + } + + static void ExpandedInformationPropertyChanged(DependencyObject source, + DependencyPropertyChangedEventArgs e) + { + TaskDialog? taskDialog = source as TaskDialog; + + if (taskDialog != null) + { + if (taskDialog.IsActivated) + { + taskDialog.SetElementText( + NativeMethods.TASKDIALOG_ELEMENTS.TDE_EXPANDED_INFORMATION, + (String)e.NewValue); + } + } + } + + static void FooterPropertyChanged(DependencyObject source, + DependencyPropertyChangedEventArgs e) + { + TaskDialog? taskDialog = source as TaskDialog; + + if (taskDialog != null) + { + if (taskDialog.IsActivated) + { + taskDialog.SetElementText( + NativeMethods.TASKDIALOG_ELEMENTS.TDE_FOOTER, + (String)e.NewValue); + } + } + } + + static void FooterIconPropertyChanged(DependencyObject source, + DependencyPropertyChangedEventArgs e) + { + TaskDialog? taskDialog = source as TaskDialog; + + if (taskDialog != null) + { + if (taskDialog.IsActivated) + { + taskDialog.UpdateIcon( + NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_FOOTER, + (ImageSource)e.NewValue); + } + } + } + + static void IconPropertyChanged(DependencyObject source, + DependencyPropertyChangedEventArgs e) + { + TaskDialog? taskDialog = source as TaskDialog; + + if (taskDialog != null) + { + if (taskDialog.IsActivated) + { + if (!taskDialog.UseDefaultIcon) + { + taskDialog.UpdateIcon( + NativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_MAIN, + (ImageSource)e.NewValue); + } + } + } + } + + static void InstructionPropertyChanged(DependencyObject source, + DependencyPropertyChangedEventArgs e) + { + TaskDialog? taskDialog = source as TaskDialog; + + if (taskDialog != null) + { + if (taskDialog.IsActivated) + { + taskDialog.SetElementText( + NativeMethods.TASKDIALOG_ELEMENTS.TDE_MAIN_INSTRUCTION, + (String)e.NewValue); + } + } + } + + #endregion + + #region Methods: Event Handler + + /// + /// Raises the event. + /// + /// An object that contains the event data. + protected virtual void OnActivated(EventArgs e) + { + activatedEventHandler?.Invoke(this, e); + } + + /// + /// Raises the event. + /// + /// An object that contains the event data. + protected virtual void OnClosed(EventArgs e) + { + closedEventHandler?.Invoke(this, e); + } + + /// + /// Raises the event. + /// + /// An object that contains the event data. + protected virtual void OnCollapsed(EventArgs e) + { + collapsedEventHandler?.Invoke(this, e); + } + + /// + /// Raises the event. + /// + /// An object that contains the event data. + protected virtual void OnExpanded(EventArgs e) + { + expandedEventHandler?.Invoke(this, e); + } + + /// + /// Raises the event. + /// + /// An object that contains the event data. + protected virtual void OnHelp(EventArgs e) + { + helpEventHandler?.Invoke(this, e); + } + + /// + /// Raises the event. + /// + /// An object that contains the event data. + protected virtual void OnInitialized(EventArgs e) + { + initializedEventHandler?.Invoke(this, e); + } + + /// + /// Raises the event. + /// + /// An object that contains the + /// timer event data. + protected virtual void OnTimer(TaskDialogTimerEventArgs e) + { + timerEventHandler?.Invoke(this, e); + } + + /// + /// Raises the event. + /// + /// An object that contains the event data. + protected virtual void OnVerificationChanged(EventArgs e) + { + verificationChangedEventHandler?.Invoke(this, e); + } + + #endregion + + #region Methods: Static + + /// + /// Displays a . + /// + /// A that specifies the instruction text + /// to display. + /// A value that specifies which common button + /// was selected by the user. + public static TaskDialogResult Show(String instruction) + { + return Show(instruction, null, null, TaskDialogButtons.None, TaskDialogIcon.None); + } + + /// + /// Displays a . + /// + /// A that specifies the instruction text + /// to display. + /// A that specifies the content text to + /// display. + /// A value that specifies which common button + /// was selected by the user. + public static TaskDialogResult Show(String instruction, String content) + { + return Show(instruction, content, null, TaskDialogButtons.None, TaskDialogIcon.None); + } + + /// + /// Displays a . + /// + /// A that specifies the instruction text + /// to display. + /// A that specifies the content text to + /// display. + /// A that specifies the title bar text of the + /// task dialog. + /// A value that specifies which common button + /// was selected by the user. + public static TaskDialogResult Show(String instruction, String content, String title) + { + return Show(instruction, content, title, TaskDialogButtons.None, TaskDialogIcon.None); + } + + /// + /// Displays a . + /// + /// A that specifies the instruction text + /// to display. + /// A that specifies the content text to + /// display. + /// A that specifies the title bar text of the + /// task dialog. + /// A value that specifies which + /// buttons to display. + /// A value that specifies which common button + /// was selected by the user. + public static TaskDialogResult Show(String instruction, String content, String title, + TaskDialogButtons buttons) + { + return Show(instruction, content, title, buttons, TaskDialogIcon.None); + } + + /// + /// Displays a . + /// + /// A that specifies the instruction text + /// to display. + /// A that specifies the content text to + /// display. + /// A that specifies the title bar text of the + /// task dialog. + /// A value that specifies which + /// buttons to display. + /// A value that specifies the icon to + /// display. + /// A value that specifies which common button + /// was selected by the user. + public static TaskDialogResult Show(string instruction, string? content, string? title, + TaskDialogButtons buttons, TaskDialogIcon icon) + { + // Initialize task dialog instance + TaskDialog taskDialog = new TaskDialog(); + taskDialog.Title = title; + taskDialog.Instruction = instruction; + taskDialog.Content = content; + taskDialog.CommonButtons = buttons; + taskDialog.DefaultIcon = icon; + + // Show instance and return result + return taskDialog.Show(); + } + + /// + /// Displays a in front of the specified window. + /// + /// A or that represents the owner of this task + /// dialog. + /// A that specifies the instruction text + /// to display. + /// A value that specifies which common button + /// was selected by the user. + public static TaskDialogResult ShowModal(object owner, String instruction) + { + return ShowModal(owner, instruction, null, null, TaskDialogButtons.None, + TaskDialogIcon.None); + } + + /// + /// Displays a in front of the specified window. + /// + /// A or that represents the owner of this task + /// dialog. + /// A that specifies the instruction text + /// to display. + /// A that specifies the content text to + /// display. + /// A value that specifies which common button + /// was selected by the user. + public static TaskDialogResult ShowModal(object owner, String instruction, String content) + { + return ShowModal(owner, instruction, content, null, TaskDialogButtons.None, + TaskDialogIcon.None); + } + + /// + /// Displays a in front of the specified window. + /// + /// A or that represents the owner of this task + /// dialog. + /// A that specifies the instruction text + /// to display. + /// A that specifies the content text to + /// display. + /// A that specifies the title bar text of the + /// task dialog. + /// A value that specifies which common button + /// was selected by the user. + public static TaskDialogResult ShowModal(object owner, String instruction, String content, + String title) + { + return ShowModal(owner, instruction, content, title, TaskDialogButtons.None, + TaskDialogIcon.None); + } + + /// + /// Displays a in front of the specified window. + /// + /// A or that represents the owner of this task + /// dialog. + /// A that specifies the instruction text + /// to display. + /// A that specifies the content text to + /// display. + /// A that specifies the title bar text of the + /// task dialog. + /// A value that specifies which + /// buttons to display. + /// A value that specifies which common button + /// was selected by the user. + public static TaskDialogResult ShowModal(object owner, String instruction, String content, + String title, TaskDialogButtons buttons) + { + return ShowModal(owner, instruction, content, title, buttons, TaskDialogIcon.None); + } + + /// + /// Displays a in front of the specified window. + /// + /// A or that represents the owner of this task + /// dialog. + /// A that specifies the instruction text + /// to display. + /// A that specifies the content text to + /// display. + /// A that specifies the title bar text of the + /// task dialog. + /// A value that specifies which + /// buttons to display. + /// A value that specifies the icon to + /// display. + /// A value that specifies which common button + /// was selected by the user. + public static TaskDialogResult ShowModal(object owner, string instruction, string? content, + string? title, TaskDialogButtons buttons, + TaskDialogIcon icon) + { + // Validate arguments + if (owner == null) + { + throw new ArgumentNullException("owner"); + } + + // Initialize task dialog instance + TaskDialog taskDialog = new TaskDialog(); + taskDialog.Title = title; + taskDialog.Instruction = instruction; + taskDialog.Content = content; + taskDialog.CommonButtons = buttons; + taskDialog.DefaultIcon = icon; + + // Show instance and return result + return taskDialog.ShowModal(owner); + } + + #endregion + + #region Methods: TaskDialog Callback Procedure + + Int32 TaskDialogProc(IntPtr hwnd, UInt32 uNotification, UIntPtr wParam, IntPtr lParam, + IntPtr dwRefData) + { + Int32 result = NativeMethods.S_OK; + + // Cast notification value + NativeMethods.TASKDIALOG_NOTIFICATIONS notification = + (NativeMethods.TASKDIALOG_NOTIFICATIONS)uNotification; + + // Handle notification + switch (notification) + { + case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_BUTTON_CLICKED: + // Get button ID + Int32 buttonID = (Int32)wParam; + + switch (buttonID) + { case NativeMethods.IDOK: case NativeMethods.IDCANCEL: case NativeMethods.IDRETRY: @@ -1590,191 +1729,213 @@ Int32 TaskDialogProc(IntPtr hwnd, UInt32 uNotification, UIntPtr wParam, IntPtr l case NativeMethods.IDCLOSE: break; default: - if (Buttons.Count != 0) { - TaskDialogButton button = Buttons[buttonID - 16]; - - // Raise Click event on button - button.RaiseClickEvent(); - - // Does the button prevent the dialog from closing? - if (button.PreventClose) { - // Note: According to MSDN, one has to return E_FAIL to prevent the task - // dialog from closing, but actually you have to return S_FALSE as using - // E_FAIL will cause the task dialog function to fail. - result = NativeMethods.S_FALSE; - } - } + if (Buttons.Count != 0) + { + TaskDialogButton button = Buttons[buttonID - 16]; + + // Raise Click event on button + button.RaiseClickEvent(); + + // Does the button prevent the dialog from closing? + if (button.PreventClose) + { + // Note: According to MSDN, one has to return E_FAIL to prevent the task + // dialog from closing, but actually you have to return S_FALSE as using + // E_FAIL will cause the task dialog function to fail. + result = NativeMethods.S_FALSE; + } + } + break; + } + break; + + case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_CREATED: + // Set IsActivated property + IsActivated = true; + + // Raise Activated event + OnActivated(EventArgs.Empty); + + break; + + case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_DESTROYED: + // Remove handle reference + Handle = IntPtr.Zero; + + // Mark as inactive and uninitialized + IsActivated = false; + IsInitialized = false; + + // Raise Closed event + OnClosed(EventArgs.Empty); + + break; + + case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_DIALOG_CONSTRUCTED: + // Set Handle property + Handle = hwnd; + + // Initialize elements and set IsInitialized property + InitializeElements(); + IsInitialized = true; + + // Raise Initialized event + OnInitialized(EventArgs.Empty); + + break; + + case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_EXPANDO_BUTTON_CLICKED: + // Set IsExpanded property + IsExpanded = ((Int32)wParam != 0); + + // Raise Expanded/Collapsed event according to expansion state + if (expanded) + { + OnExpanded(EventArgs.Empty); + } + else + { + OnCollapsed(EventArgs.Empty); + } + + break; + + case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_HELP: + // Raise Help event + OnHelp(EventArgs.Empty); + + break; + + case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_HYPERLINK_CLICKED: + // Marshal URL string + String url = Marshal.PtrToStringUni(lParam); + + // Find corresponding link and raise its Click event + Boolean eventRaised = false; + TaskDialogText taskDialogText; + TaskDialogLink taskDialogLink; + + if (Content is TaskDialogText) + { + // Check Content for event source + taskDialogText = (TaskDialogText)Content; + foreach (TaskDialogTextElement element in taskDialogText.Contents) + { + if (element is TaskDialogLink) + { + taskDialogLink = (TaskDialogLink)element; + if (url.Equals(taskDialogLink.Uri.ToString())) + { + taskDialogLink.RaiseClickEvent(); + eventRaised = true; + break; + } + } + } + if (eventRaised) + { + break; + } + } + + if (ExpandedInformation is TaskDialogText) + { + // Check ExpandedInformation for event source + taskDialogText = (TaskDialogText)ExpandedInformation; + foreach (TaskDialogTextElement element in taskDialogText.Contents) + { + if (element is TaskDialogLink) + { + taskDialogLink = (TaskDialogLink)element; + if (url.Equals(taskDialogLink.Uri.ToString())) + { + taskDialogLink.RaiseClickEvent(); + eventRaised = true; + break; + } + } + } + if (eventRaised) + { break; + } + } + + if (Footer is TaskDialogText) + { + // Check Footer for event source + taskDialogText = (TaskDialogText)Footer; + foreach (TaskDialogTextElement element in taskDialogText.Contents) + { + if (element is TaskDialogLink) + { + taskDialogLink = (TaskDialogLink)element; + if (url.Equals(taskDialogLink.Uri.ToString())) + { + taskDialogLink.RaiseClickEvent(); + break; + } + } + } + } + + break; + + case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_RADIO_BUTTON_CLICKED: + // Get radio button ID + Int32 radioButtonID = (Int32)wParam; + + // Lookup radio button instance from collection + TaskDialogRadioButton radioButton = RadioButtons[radioButtonID]; + + // Update IsChecked property + foreach (TaskDialogRadioButton radioBtn in RadioButtons) + { + // Remove check state from all but the clicked radio button + if (radioButton != radioBtn) + { + radioBtn.IsChecked = false; + } } - break; - - case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_CREATED: - // Set IsActivated property - IsActivated = true; - - // Raise Activated event - OnActivated(EventArgs.Empty); - - break; - - case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_DESTROYED: - // Remove handle reference - Handle = IntPtr.Zero; - - // Mark as inactive and uninitialized - IsActivated = false; - IsInitialized = false; - - // Raise Closed event - OnClosed(EventArgs.Empty); - - break; - - case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_DIALOG_CONSTRUCTED: - // Set Handle property - Handle = hwnd; - - // Initialize elements and set IsInitialized property - InitializeElements(); - IsInitialized = true; - - // Raise Initialized event - OnInitialized(EventArgs.Empty); - - break; - - case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_EXPANDO_BUTTON_CLICKED: - // Set IsExpanded property - IsExpanded = ((Int32)wParam != 0); - - // Raise Expanded/Collapsed event according to expansion state - if (expanded) { - OnExpanded(EventArgs.Empty); - } else { - OnCollapsed(EventArgs.Empty); - } - - break; - - case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_HELP: - // Raise Help event - OnHelp(EventArgs.Empty); - - break; - - case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_HYPERLINK_CLICKED: - // Marshal URL string - String url = Marshal.PtrToStringUni(lParam); - - // Find corresponding link and raise its Click event - Boolean eventRaised = false; - TaskDialogText taskDialogText; - TaskDialogLink taskDialogLink; - - if (Content is TaskDialogText) { - // Check Content for event source - taskDialogText = (TaskDialogText)Content; - foreach (TaskDialogTextElement element in taskDialogText.Contents) { - if (element is TaskDialogLink) { - taskDialogLink = (TaskDialogLink)element; - if (url.Equals(taskDialogLink.Uri.ToString())) { - taskDialogLink.RaiseClickEvent(); - eventRaised = true; - break; - } - } - } - if (eventRaised) { - break; - } - } - - if (ExpandedInformation is TaskDialogText) { - // Check ExpandedInformation for event source - taskDialogText = (TaskDialogText)ExpandedInformation; - foreach (TaskDialogTextElement element in taskDialogText.Contents) { - if (element is TaskDialogLink) { - taskDialogLink = (TaskDialogLink)element; - if (url.Equals(taskDialogLink.Uri.ToString())) { - taskDialogLink.RaiseClickEvent(); - eventRaised = true; - break; - } - } - } - if (eventRaised) { - break; - } - } - - if (Footer is TaskDialogText) { - // Check Footer for event source - taskDialogText = (TaskDialogText)Footer; - foreach (TaskDialogTextElement element in taskDialogText.Contents) { - if (element is TaskDialogLink) { - taskDialogLink = (TaskDialogLink)element; - if (url.Equals(taskDialogLink.Uri.ToString())) { - taskDialogLink.RaiseClickEvent(); - break; - } - } - } - } - - break; - - case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_RADIO_BUTTON_CLICKED: - // Get radio button ID - Int32 radioButtonID = (Int32)wParam; - - // Lookup radio button instance from collection - TaskDialogRadioButton radioButton = RadioButtons[radioButtonID]; - - // Update IsChecked property - foreach (TaskDialogRadioButton radioBtn in RadioButtons) { - // Remove check state from all but the clicked radio button - if (radioButton != radioBtn) { - radioBtn.IsChecked = false; - } - } - - radioButton.IsChecked = true; - - // Raise Click event on radio button - radioButton.RaiseClickEvent(); - - break; - - case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_TIMER: - // Create and initialize event arguments object - Int32 tickCount = (Int32)wParam; - TaskDialogTimerEventArgs timerEventArgs = new TaskDialogTimerEventArgs(tickCount); - - // Raise Timer event - OnTimer(timerEventArgs); - - // Check reset property of event arguments - // If set to true by the callee, the timer will be reset - if (timerEventArgs.Reset) { - // Reset indicated by S_FALSE result - result = NativeMethods.S_FALSE; - } - - break; - - case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_VERIFICATION_CLICKED: - // Check verification property - verificationChecked = ((Int32)wParam != 0); - - // Raise VerificationChanged event - OnVerificationChanged(EventArgs.Empty); - - break; - } - - return result; - } - - #endregion - } + + radioButton.IsChecked = true; + + // Raise Click event on radio button + radioButton.RaiseClickEvent(); + + break; + + case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_TIMER: + // Create and initialize event arguments object + Int32 tickCount = (Int32)wParam; + TaskDialogTimerEventArgs timerEventArgs = new TaskDialogTimerEventArgs(tickCount); + + // Raise Timer event + OnTimer(timerEventArgs); + + // Check reset property of event arguments + // If set to true by the callee, the timer will be reset + if (timerEventArgs.Reset) + { + // Reset indicated by S_FALSE result + result = NativeMethods.S_FALSE; + } + + break; + + case NativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_VERIFICATION_CLICKED: + // Check verification property + verificationChecked = ((Int32)wParam != 0); + + // Raise VerificationChanged event + OnVerificationChanged(EventArgs.Empty); + + break; + } + + return result; + } + + #endregion + } } diff --git a/src/TaskDialogLib/TaskDialogButton.cs b/src/TaskDialogLib/TaskDialogButton.cs index e56430f..20a2492 100644 --- a/src/TaskDialogLib/TaskDialogButton.cs +++ b/src/TaskDialogLib/TaskDialogButton.cs @@ -51,7 +51,7 @@ public class TaskDialogButton : TaskDialogButtonBase /// Indentifies the dependency property. /// public static readonly DependencyProperty DescriptionProperty = - DependencyProperty.Register("Description", typeof(String), typeof(TaskDialogButton), + DependencyProperty.Register("Description", typeof(Object), typeof(TaskDialogButton), new PropertyMetadata(null)); #endregion @@ -82,8 +82,8 @@ public Boolean ElevationRequired { /// The value of this property has no effect if the of /// the owner task dialog is set to Normal. /// - public String Description { - get { return GetValue(DescriptionProperty) as String; } + public Object Description { + get { return GetValue(DescriptionProperty) as Object; } set { SetValue(DescriptionProperty, value); } } diff --git a/src/TaskDialogLib/TaskDialogButtonDescription.cs b/src/TaskDialogLib/TaskDialogButtonDescription.cs new file mode 100644 index 0000000..8749ec4 --- /dev/null +++ b/src/TaskDialogLib/TaskDialogButtonDescription.cs @@ -0,0 +1,57 @@ +using System; +using System.Windows; +using System.Windows.Markup; + +namespace Flatcode.Presentation +{ + /// + /// Represents formatted content of a . + /// + [ContentProperty("Contents")] + public sealed class TaskDialogButtonDescription : DependencyObject + { + #region Fields + + readonly TaskDialogButtonDescriptionElementCollection contents; + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the TaskDialogButtonDescription class. + /// + public TaskDialogButtonDescription() + { + contents = new TaskDialogButtonDescriptionElementCollection(); + } + + #endregion + + #region Properties + + /// + /// Gets a that represents the contents of + /// this . + /// + public TaskDialogButtonDescriptionElementCollection Contents + { + get { return contents; } + } + + #endregion + + #region Methods: Overridden + + /// + /// Returns a string that represents this . + /// + /// A that represent the current instance. + public override String ToString() + { + return Contents.ToString(); + } + + #endregion + } +} diff --git a/src/TaskDialogLib/TaskDialogButtonDescriptionElement.cs b/src/TaskDialogLib/TaskDialogButtonDescriptionElement.cs new file mode 100644 index 0000000..3ac0b30 --- /dev/null +++ b/src/TaskDialogLib/TaskDialogButtonDescriptionElement.cs @@ -0,0 +1,61 @@ +using System; +using System.Windows; +using System.Windows.Markup; + +namespace Flatcode.Presentation +{ + /// + /// Represents the base class for all task dialog button description elements. + /// + [ContentProperty("Text")] + public abstract class TaskDialogButtonDescriptionElement : TaskDialogElement + { + #region Fields: Dependency Properties + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register("Text", typeof(String), typeof(TaskDialogButtonDescriptionElement), + new PropertyMetadata(null)); + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the TaskDialogButtonDescriptionElement class. + /// + protected TaskDialogButtonDescriptionElement() + { + } + + #endregion + + #region Properties + + /// + /// Gets or sets the text of this . + /// + public String Text + { + get { return GetValue(TextProperty) as String; } + set { SetValue(TextProperty, value); } + } + + #endregion + + #region Methods: Overridden + + /// + /// Returns a string that represents this . + /// + /// A that represents the current instance. + public override String ToString() + { + return Text; + } + + #endregion + } +} \ No newline at end of file diff --git a/src/TaskDialogLib/TaskDialogButtonDescriptionElementCollection.cs b/src/TaskDialogLib/TaskDialogButtonDescriptionElementCollection.cs new file mode 100644 index 0000000..ffea0cb --- /dev/null +++ b/src/TaskDialogLib/TaskDialogButtonDescriptionElementCollection.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Markup; + +namespace Flatcode.Presentation +{ + /// + /// Represents a collection of objects. + /// + [ContentWrapper(typeof(TaskDialogButtonDescriptionRun))] + [WhitespaceSignificantCollection] + public class TaskDialogButtonDescriptionElementCollection : + TaskDialogElementCollection + { + #region Methods + + /// + /// Adds a instance to this + /// . + /// + /// The to be added. + public void AddRun(TaskDialogButtonDescriptionRun item) + { + Add(item); + } + + #endregion + + #region Methods: Overridden + + /// + /// This method is implementation-specific and not intended to be used from third-party + /// code. + /// + /// This argument is implementation-specific and not intended to be used + /// from third-party code. + /// The return value is implementation-specific and not intended to be used from + /// third-party code. + protected internal override Int32 AddInternal(Object item) + { + if (item is String s) + { + if (s == " ") + return -1; + + item = new TaskDialogButtonDescriptionRun(s); + } + + return base.AddInternal(item); + } + + /// + /// Returns a string that represents this . + /// + /// A that represents the current instance. + public override String ToString() + { + StringBuilder sb = new StringBuilder(); + + foreach (TaskDialogButtonDescriptionElement item in this) + { + sb.Append(item.ToString()); + } + + return sb.ToString(); + } + + #endregion + } +} diff --git a/src/TaskDialogLib/TaskDialogButtonDescriptionLineBreak.cs b/src/TaskDialogLib/TaskDialogButtonDescriptionLineBreak.cs new file mode 100644 index 0000000..adc3b7a --- /dev/null +++ b/src/TaskDialogLib/TaskDialogButtonDescriptionLineBreak.cs @@ -0,0 +1,30 @@ +using Flatcode.Presentation; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; + +namespace Flatcode.Presentation +{ + public class TaskDialogButtonDescriptionLineBreak : TaskDialogButtonDescriptionElement + { + public static readonly DependencyProperty ParagraphProperty = + DependencyProperty.Register(nameof(Paragraph), typeof(bool), typeof(TaskDialogButtonDescriptionLineBreak), + new PropertyMetadata(null)); + + public bool Paragraph + { + get { return (bool)GetValue(ParagraphProperty); } + set { SetValue(ParagraphProperty, value); } + } + + public override string ToString() + { + if (Paragraph) + return "\n\n"; + + return "\n"; + } + } +} diff --git a/src/TaskDialogLib/TaskDialogButtonDescriptionRun.cs b/src/TaskDialogLib/TaskDialogButtonDescriptionRun.cs new file mode 100644 index 0000000..58c43d2 --- /dev/null +++ b/src/TaskDialogLib/TaskDialogButtonDescriptionRun.cs @@ -0,0 +1,31 @@ +using System; + +namespace Flatcode.Presentation +{ + /// + /// Represents an inline run on a . + /// + public class TaskDialogButtonDescriptionRun : TaskDialogButtonDescriptionElement + { + #region Constructors + + /// + /// Initializes a new instance of the TaskDialogButtonDescriptionRun class. + /// + public TaskDialogButtonDescriptionRun() + { + } + + /// + /// Initializes a new instance of the TaskDialogButtonDescriptionRun with the given text. + /// + /// A that represents the text of the run. + public TaskDialogButtonDescriptionRun(String text) + { + // Initialize instance + Text = text; + } + + #endregion + } +} diff --git a/src/TaskDialogLib/TaskDialogElement.cs b/src/TaskDialogLib/TaskDialogElement.cs index 399e88e..3668b4e 100644 --- a/src/TaskDialogLib/TaskDialogElement.cs +++ b/src/TaskDialogLib/TaskDialogElement.cs @@ -28,6 +28,7 @@ using System; using System.Windows; +using System.Windows.Markup; #endregion @@ -36,6 +37,7 @@ namespace Flatcode.Presentation /// /// Represents the base class for all task dialog elements. /// + [RuntimeNameProperty(nameof(Name))] public abstract class TaskDialogElement : DependencyObject { #region Fields @@ -57,10 +59,23 @@ protected TaskDialogElement() #region Properties - /// - /// Gets or sets the owner of this . - /// - protected internal TaskDialog Owner { + + private static readonly DependencyProperty NameProperty = + DependencyProperty.Register(nameof(Name), typeof(string), typeof(TaskDialogElement)); + + /// + /// The name of this . + /// + public string Name + { + get => (string)GetValue(NameProperty); + set => SetValue(NameProperty, value); + } + + /// + /// Gets or sets the owner of this . + /// + protected internal TaskDialog Owner { get { if (ownerReference != null) { if (ownerReference.IsAlive) { diff --git a/src/TaskDialogLib/TaskDialogLib.csproj b/src/TaskDialogLib/TaskDialogLib.csproj index 7158b36..4a6e28d 100644 --- a/src/TaskDialogLib/TaskDialogLib.csproj +++ b/src/TaskDialogLib/TaskDialogLib.csproj @@ -25,6 +25,7 @@ prompt 4 false + 8.0 none @@ -33,11 +34,18 @@ prompt 4 false + 8.0 + + + + + + diff --git a/src/TaskDialogLib/TaskDialogLineBreak.cs b/src/TaskDialogLib/TaskDialogLineBreak.cs new file mode 100644 index 0000000..d8d34ce --- /dev/null +++ b/src/TaskDialogLib/TaskDialogLineBreak.cs @@ -0,0 +1,30 @@ +using Flatcode.Presentation; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; + +namespace Flatcode.Presentation +{ + public class TaskDialogLineBreak : TaskDialogTextElement + { + public static readonly DependencyProperty ParagraphProperty = + DependencyProperty.Register(nameof(Paragraph), typeof(bool), typeof(TaskDialogLineBreak), + new PropertyMetadata(null)); + + public bool Paragraph + { + get { return (bool)GetValue(ParagraphProperty); } + set { SetValue(ParagraphProperty, value); } + } + + public override string ToString() + { + if (Paragraph) + return "\n\n"; + + return "\n"; + } + } +} diff --git a/src/TaskDialogLib/TaskDialogTextElementCollection.cs b/src/TaskDialogLib/TaskDialogTextElementCollection.cs index 03c6427..880102d 100644 --- a/src/TaskDialogLib/TaskDialogTextElementCollection.cs +++ b/src/TaskDialogLib/TaskDialogTextElementCollection.cs @@ -78,8 +78,16 @@ public void AddRun(TaskDialogRun item) /// third-party code. protected internal override Int32 AddInternal(Object item) { - if (item is String) { - item = new TaskDialogRun((String)item); + if (item is String s) { + /* + * XAML will coalesce all whitespace into a single space. If + * there are no non-whitespace characters, ignore this part. + */ + if (s == " ") + return -1; + + // if there _is_ a non-whitespace character, create a new Run. + item = new TaskDialogRun(s); } return base.AddInternal(item); diff --git a/src/TaskDialogLibTest/TaskDialogLibTest.csproj b/src/TaskDialogLibTest/TaskDialogLibTest.csproj index 65ace88..e6bc049 100644 --- a/src/TaskDialogLibTest/TaskDialogLibTest.csproj +++ b/src/TaskDialogLibTest/TaskDialogLibTest.csproj @@ -27,6 +27,7 @@ prompt 4 false + 8.0 AnyCPU @@ -36,6 +37,7 @@ prompt 4 false + 8.0 App.manifest