/// <summary>
        /// Creates, displays, and operates a task dialog. The task dialog contains application-defined messages, title,
        /// verification check box, command links and push buttons, plus any combination of predefined icons and push buttons
        /// as specified on the other members of the class before calling Show.
        /// </summary>
        /// <param name="hwndOwner">Owner window the task Dialog will modal to.</param>
        /// <param name="verificationFlagChecked">Returns true if the verification checkbox was checked when the dialog
        /// was dismissed.</param>
        /// <param name="radioButtonResult">The radio botton selected by the user.</param>
        /// <returns>The result of the dialog, either a DialogResult value for common push buttons set in the CommonButtons
        /// member or the ButtonID from a TaskDialogButton structure set on the Buttons member.</returns>
        private int PrivateShow(IntPtr hwndOwner, out bool verificationFlagChecked, out int radioButtonResult)
        {
            verificationFlagChecked = false;
            radioButtonResult = 0;
            int result;
            UnsafeNativeMethods.TASKDIALOGCONFIG config = new UnsafeNativeMethods.TASKDIALOGCONFIG();

            try
            {
                config.cbSize = (uint)UnsafeNativeMethods.TASKDIALOGCONFIG.SizeOf;
                config.hwndParent = hwndOwner;
                config.dwFlags = this.flags;
                config.dwCommonButtons = this.commonButtons;

                if (!string.IsNullOrEmpty(this.windowTitle))
                {
                    config.pszWindowTitle = this.windowTitle;
                }

                config.MainIcon = (IntPtr)this.mainIcon;
                if (this.customMainIcon != null)
                {
                    config.dwFlags |= UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_MAIN;
                    config.MainIcon = this.customMainIcon.Handle;
                }

                if (!string.IsNullOrEmpty(this.mainInstruction))
                {
                    config.pszMainInstruction = this.mainInstruction;
                }

                if (!string.IsNullOrEmpty(this.content))
                {
                    config.pszContent = this.content;
                }

                TaskDialogButton[] customButtons = this.buttons;
                if (customButtons.Length > 0)
                {
                    // Hand marshal the buttons array.
                    int elementSize = TaskDialogButton.SizeOf;
                    config.pButtons = MemoryAlloc.PrivateHeap.Allocate(elementSize * customButtons.Length);
                    for (int i = 0; i < customButtons.Length; i++)
                    {
                        unsafe // Unsafe because of pointer arithmatic.
                        {
                            byte* p = (byte*)config.pButtons;
                            Marshal.StructureToPtr(customButtons[i], (IntPtr)(p + (elementSize * i)), false);
                        }

                        config.cButtons++;
                    }
                }

                TaskDialogButton[] customRadioButtons = this.radioButtons;
                if (customRadioButtons.Length > 0)
                {
                    // Hand marshal the buttons array.
                    int elementSize = TaskDialogButton.SizeOf;
                    config.pRadioButtons = MemoryAlloc.PrivateHeap.Allocate(elementSize * customRadioButtons.Length);
                    for (int i = 0; i < customRadioButtons.Length; i++)
                    {
                        unsafe // Unsafe because of pointer arithmatic.
                        {
                            byte* p = (byte*)config.pRadioButtons;
                            Marshal.StructureToPtr(customRadioButtons[i], (IntPtr)(p + (elementSize * i)), false);
                        }

                        config.cRadioButtons++;
                    }
                }

                config.nDefaultButton = this.defaultButton;
                config.nDefaultRadioButton = this.defaultRadioButton;

                if (!string.IsNullOrEmpty(this.verificationText))
                {
                    config.pszVerificationText = this.verificationText;
                }

                if (!string.IsNullOrEmpty(this.expandedInformation))
                {
                    config.pszExpandedInformation = this.expandedInformation;
                }

                if (!string.IsNullOrEmpty(this.expandedControlText))
                {
                    config.pszExpandedControlText = this.expandedControlText;
                }

                if (!string.IsNullOrEmpty(this.collapsedControlText))
                {
                    config.pszCollapsedControlText = this.CollapsedControlText;
                }

                config.FooterIcon = (IntPtr)this.footerIcon;
                if (this.customFooterIcon != null)
                {
                    config.dwFlags |= UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_FOOTER;
                    config.FooterIcon = this.customFooterIcon.Handle;
                }

                if (!string.IsNullOrEmpty(this.footer))
                {
                    config.pszFooter = this.footer;
                }

                // If our user has asked for a callback then we need to ask for one to
                // translate to the friendly version.
                if (this.callback != null)
                {
                    config.pfCallback = this.PrivateCallback;
                }

                ////config.lpCallbackData = this.callbackData; // How do you do this? Need to pin the ref?
                config.cxWidth = this.width;

                // The call all this mucking about is here for.
                UnsafeNativeMethods.TaskDialogIndirect(ref config, out result, out radioButtonResult, out verificationFlagChecked);
            }
            finally
            {
                // Free the unmanged memory needed for the button arrays.
                // There is the possiblity of leaking memory if the app-domain is destroyed in a non clean way
                // and the hosting OS process is kept alive but fixing this would require using hardening techniques
                // that are not required for the users of this class.
                if (config.pButtons != IntPtr.Zero)
                {
                    int elementSize = TaskDialogButton.SizeOf;
                    for (int i = 0; i < config.cButtons; i++)
                    {
                        unsafe
                        {
                            byte* p = (byte*)config.pButtons;
                            Marshal.DestroyStructure((IntPtr)(p + (elementSize * i)), typeof(TaskDialogButton));
                        }
                    }

                    MemoryAlloc.PrivateHeap.Free(config.pButtons);
                }

                if (config.pRadioButtons != IntPtr.Zero)
                {
                    int elementSize = TaskDialogButton.SizeOf;
                    for (int i = 0; i < config.cRadioButtons; i++)
                    {
                        unsafe
                        {
                            byte* p = (byte*)config.pRadioButtons;
                            Marshal.DestroyStructure((IntPtr)(p + (elementSize * i)), typeof(TaskDialogButton));
                        }
                    }

                    MemoryAlloc.PrivateHeap.Free(config.pRadioButtons);
                }
            }

            return result;
        }
Exemple #2
0
 private int PrivateShow(IntPtr hwndOwner, out bool verificationFlagChecked, out int radioButtonResult)
 {
     verificationFlagChecked = false;
     radioButtonResult = 0;
     int result = 0;
     UnsafeNativeMethods.TASKDIALOGCONFIG config = new UnsafeNativeMethods.TASKDIALOGCONFIG();
     try
     {
         config.cbSize = (uint)Marshal.SizeOf(typeof(UnsafeNativeMethods.TASKDIALOGCONFIG));
         config.hwndParent = hwndOwner;
         config.dwFlags = this.flags;
         config.dwCommonButtons = this.commonButtons;
         if (!string.IsNullOrEmpty(this.windowTitle))
         {
             config.pszWindowTitle = this.windowTitle;
         }
         config.MainIcon = (IntPtr)this.mainIcon;
         if (this.customMainIcon != null)
         {
             config.dwFlags |= UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_MAIN;
             config.MainIcon = this.customMainIcon.Handle;
         }
         if (!string.IsNullOrEmpty(this.mainInstruction))
         {
             config.pszMainInstruction = this.mainInstruction;
         }
         if (!string.IsNullOrEmpty(this.content))
         {
             config.pszContent = this.content;
         }
         TaskDialogButton[] customButtons = this.buttons;
         if (customButtons.Length > 0)
         {
             int elementSize = Marshal.SizeOf(typeof(TaskDialogButton));
             config.pButtons = Marshal.AllocHGlobal(elementSize * (int)customButtons.Length);
             for (int i = 0; i < customButtons.Length; i++)
             {
                 unsafe
                 {
                     byte* p = (byte*)config.pButtons;
                     Marshal.StructureToPtr(customButtons[i], (IntPtr)(p + (elementSize * i)), false);
                 }
                 config.cButtons++;
             }
         }
         TaskDialogButton[] customRadioButtons = this.radioButtons;
         if (customRadioButtons.Length > 0)
         {
             int elementSize = Marshal.SizeOf(typeof(TaskDialogButton));
             config.pRadioButtons = Marshal.AllocHGlobal(elementSize * (int)customRadioButtons.Length);
             for (int i = 0; i < customRadioButtons.Length; i++)
             {
                 unsafe
                 {
                     byte* p = (byte*)config.pRadioButtons;
                     Marshal.StructureToPtr(customRadioButtons[i], (IntPtr)(p + (elementSize * i)), false);
                 }
                 config.cRadioButtons++;
             }
         }
         config.nDefaultButton = this.defaultButton;
         config.nDefaultRadioButton = this.defaultRadioButton;
         if (!string.IsNullOrEmpty(this.verificationText))
         {
             config.pszVerificationText = this.verificationText;
         }
         if (!string.IsNullOrEmpty(this.expandedInformation))
         {
             config.pszExpandedInformation = this.expandedInformation;
         }
         if (!string.IsNullOrEmpty(this.expandedControlText))
         {
             config.pszExpandedControlText = this.expandedControlText;
         }
         if (!string.IsNullOrEmpty(this.collapsedControlText))
         {
             config.pszCollapsedControlText = this.CollapsedControlText;
         }
         config.FooterIcon = (IntPtr)this.footerIcon;
         if (this.customFooterIcon != null)
         {
             config.dwFlags |= UnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_FOOTER;
             config.FooterIcon = this.customFooterIcon.Handle;
         }
         if (!string.IsNullOrEmpty(this.footer))
         {
             config.pszFooter = this.footer;
         }
         if (this.callback != null)
         {
             config.pfCallback = new UnsafeNativeMethods.TaskDialogCallback(this.PrivateCallback);
         }
         config.cxWidth = this.width;
         UnsafeNativeMethods.TaskDialogIndirect(ref config, out result, out radioButtonResult, out verificationFlagChecked);
     }
     finally
     {
         if (config.pButtons != IntPtr.Zero)
         {
             int elementSize = Marshal.SizeOf(typeof(TaskDialogButton));
             for (int i = 0; i < config.cButtons; i++)
             {
                 unsafe
                 {
                     byte* p = (byte*)config.pButtons;
                     Marshal.DestroyStructure((IntPtr)(p + (elementSize * i)), typeof(TaskDialogButton));
                 }
             }
             Marshal.FreeHGlobal(config.pButtons);
         }
         if (config.pRadioButtons != IntPtr.Zero)
         {
             int elementSize = Marshal.SizeOf(typeof(TaskDialogButton));
             for (int i = 0; i < config.cRadioButtons; i++)
             {
                 unsafe
                 {
                     byte* p = (byte*)config.pRadioButtons;
                     Marshal.DestroyStructure((IntPtr)(p + (elementSize * i)), typeof(TaskDialogButton));
                 }
             }
             Marshal.FreeHGlobal(config.pRadioButtons);
         }
     }
     return result;
 }