Click here to Skip to main content
13,835,124 members
Click here to Skip to main content

Stats

152.6K views
18.5K downloads
227 bookmarked
Posted 1 Jan 2010
Licenced CPOL

Task Manager

, 1 Jan 2010
Manage your daily tasks and To-Do list using some exciting features of Windows 7.
TaskManager
Core
AppRestartRecovery
Dialogs
Common
TaskDialogs
Interop
AppRestartRecovery
Dialogs
NetworkList
PowerManagement
TaskDialogs
NetworkList
PowerManagement
Properties
PropertySystem
SafeHandles
Shell
Common
CommonFileDialogs
Controls
Design
ShellObjects.cd
ShellThumbnailClassDiagram.cd
DesktopWindowManager
ExplorerBrowser
ExplorerBrowserDiagram.cd
Interop
Common
Dialogs
ExplorerBrowser
KnownFolders
PropertySystem
StockIcons
Taskbar
KnownFolders
Properties
PropertySystem
StockIcons
Taskbar
TaskManager
Common
Controls
Database
SqlTaskManager.edmx
TaskManager.mdf
TaskManager_log.LDF
Properties
Resources
Add.png
AddCategory.png
AddResource.png
AddTask.png
Back.ico
backcolor.bmp
BlueCat.png
Blue_Category.ico
bold.bmp
Category.png
Category_Icon.ico
Close.bmp
Close.png
color.bmp
Delete.png
Delete_01.png
Delete_Icon.ico
edit.png
edit_Icon.ico
Empty.png
Forward.ico
GanttChart.png
GreenCat.png
Green_Category.ico
High_Priority.png
High_Priority_Icon.ico
indent.bmp
italic.bmp
Low_Priority.png
Low_Priority_Icon.ico
Medium_Priority.png
Medium_Priority_Icon.ico
NextWeek_Flag.png
NextWeek_Flag_Icon.ico
NoDate_Flag.png
NoDate_Flag_Icon.ico
ol.bmp
OrangeCat.png
Orange_Category.ico
outdent.bmp
PurpleCat.png
Purple_Category.ico
Question.ico
Question_Icon.ico
RedCat.png
Red_Category.ico
Resource.png
Resource_Icon.ico
Save.bmp
Save.png
Task manager.ico
Task.png
TaskSetting.png
Task_Icon.ico
ThisWeek_Flag.png
ThisWeek_Flag_Icon.ico
Today_Flag.png
Today_Flag_Icon.ico
Tomorrow_Flag.png
Tomorrow_Flag_Icon.ico
underscore.bmp
uol.bmp
YellowCat.png
Yellow_Category.ico
TaskManager.csproj.user
Window7
TaskManagerSimple
TaskManagerSimple
Common
Controls
Database
SqlTaskManager.edmx
TaskManager.mdf
TaskManager_log.LDF
Properties
Resources
Add.png
AddCategory.png
AddResource.png
AddTask.png
Back.ico
backcolor.bmp
BlueCat.png
Blue_Category.ico
bold.bmp
Category.png
Category_Icon.ico
Close.bmp
Close.png
color.bmp
Delete.png
Delete_01.png
Delete_Icon.ico
edit.png
edit_Icon.ico
Empty.png
Forward.ico
GanttChart.png
GreenCat.png
Green_Category.ico
High_Priority.png
High_Priority_Icon.ico
indent.bmp
italic.bmp
Low_Priority.png
Low_Priority_Icon.ico
Medium_Priority.png
Medium_Priority_Icon.ico
NextWeek_Flag.png
NextWeek_Flag_Icon.ico
NoDate_Flag.png
NoDate_Flag_Icon.ico
ol.bmp
OrangeCat.png
Orange_Category.ico
outdent.bmp
PurpleCat.png
Purple_Category.ico
Question.ico
Question_Icon.ico
RedCat.png
Red_Category.ico
Resource.png
Resource_Icon.ico
Save.bmp
Save.png
Task manager.ico
Task.png
TaskSetting.png
Task_Icon.ico
ThisWeek_Flag.png
ThisWeek_Flag_Icon.ico
Today_Flag.png
Today_Flag_Icon.ico
Tomorrow_Flag.png
Tomorrow_Flag_Icon.ico
underscore.bmp
uol.bmp
YellowCat.png
Yellow_Category.ico
TaskManager.csproj.user
//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using MS.WindowsAPICodePack.Internal;

namespace Microsoft.WindowsAPICodePack.Dialogs
{
    /// <summary>
    /// Encapsulates the native logic required to create, 
    /// configure, and show a TaskDialog, 
    /// via the TaskDialogIndirect() Win32 function.
    /// </summary>
    /// <remarks>A new instance of this class should 
    /// be created for each messagebox show, as
    /// the HWNDs for TaskDialogs do not remain constant 
    /// across calls to TaskDialogIndirect.
    /// </remarks>
    internal class NativeTaskDialog : IDisposable
    {
        private TaskDialogNativeMethods.TASKDIALOGCONFIG nativeDialogConfig;
        private NativeTaskDialogSettings settings;
        private IntPtr hWndDialog;
        private TaskDialog outerDialog;

        private IntPtr[] updatedStrings = new IntPtr[Enum.GetNames(typeof(TaskDialogNativeMethods.TASKDIALOG_ELEMENTS)).Length];
        private IntPtr buttonArray, radioButtonArray;

        // Flag tracks whether our first radio 
        // button click event has come through.
        private bool firstRadioButtonClicked = true;

        #region Constructors

        // Configuration is applied at dialog creation time.
        internal NativeTaskDialog( 
            NativeTaskDialogSettings settings,
            TaskDialog outerDialog)
        {
            nativeDialogConfig = settings.NativeConfiguration;
            this.settings = settings;

            // Wireup dialog proc message loop for this instance.
            nativeDialogConfig.pfCallback = 
                new TaskDialogNativeMethods.PFTASKDIALOGCALLBACK(DialogProc);

            // Keep a reference to the outer shell, so we can notify.
            this.outerDialog = outerDialog;
        }

        #endregion

        #region Public Properties

        private DialogShowState showState = 
            DialogShowState.PreShow;

        public DialogShowState ShowState
        {
            get { return showState; }
        }

        private int selectedButtonID;
        internal int SelectedButtonID
        {
            get { return selectedButtonID; }
        }

        private int selectedRadioButtonID;
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal int SelectedRadioButtonID
        {
            get { return selectedRadioButtonID; }
        }

        private bool checkBoxChecked;
        internal bool CheckBoxChecked
        {
            get { return checkBoxChecked; }
        }

        #endregion

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object)",
            Justification = "We are not currently handling globalization or localization")]
        internal void NativeShow()
        {
            // Applies config struct and other settings, then
            // calls main Win32 function.
            if (settings == null)
                throw new InvalidOperationException(
                    "An error has occurred in dialog configuration.");

            // Do a last-minute parse of the various dialog control lists,  
            // and only allocate the memory at the last minute.

            MarshalDialogControlStructs();
            // Make the call and show the dialog.
            // NOTE: this call is BLOCKING, though the thread 
            // WILL re-enter via the DialogProc.
            try
            {
                showState = DialogShowState.Showing;

                // Here is the way we use "vanilla" P/Invoke to call 
                // TaskDialogIndirect().  
                HRESULT hresult = TaskDialogNativeMethods.TaskDialogIndirect(
                    nativeDialogConfig,
                    out selectedButtonID,
                    out selectedRadioButtonID,
                    out checkBoxChecked);

                if (CoreErrorHelper.Failed(hresult))
                {
                    string msg;
                    switch (hresult)
                    {
                        case HRESULT.E_INVALIDARG:
                            msg = "Invalid arguments to Win32 call.";
                            break;
                        case HRESULT.E_OUTOFMEMORY:
                            msg = "Dialog contents too complex.";
                            break;
                        default:
                            msg = String.Format(

                                "An unexpected internal error occurred in the Win32 call:{0:x}",
                                hresult);
                            break;
                    }
                    Exception e = Marshal.GetExceptionForHR((int)hresult);
                    throw new Win32Exception(msg, e);
                }
            }
            catch (EntryPointNotFoundException)
            {
                throw new NotSupportedException("TaskDialog feature needs to load version 6 of comctl32.dll but a different version is current loaded in memory.");
            }
            finally
            {
                showState = DialogShowState.Closed;
            }
        }

        // The new task dialog does not support the existing 
        // Win32 functions for closing (e.g. EndDialog()); instead,
        // a "click button" message is sent. In this case, we're 
        // abstracting out to say that the TaskDialog consumer can
        // simply call "Close" and we'll "click" the cancel button. 
        // Note that the cancel button doesn't actually
        // have to exist for this to work.
        internal void NativeClose(TaskDialogResult result)
        {
            showState = DialogShowState.Closing;

            int id = (int)TaskDialogNativeMethods.TASKDIALOG_COMMON_BUTTON_RETURN_ID.IDCANCEL;

            if(result == TaskDialogResult.Close)
                id = (int)TaskDialogNativeMethods.TASKDIALOG_COMMON_BUTTON_RETURN_ID.IDCLOSE;
            else if(result == TaskDialogResult.CustomButtonClicked)
                id = DialogsDefaults.MinimumDialogControlId; // custom buttons
            else if(result == TaskDialogResult.No)
                id = (int)TaskDialogNativeMethods.TASKDIALOG_COMMON_BUTTON_RETURN_ID.IDNO;
            else if(result == TaskDialogResult.Ok)
                id = (int)TaskDialogNativeMethods.TASKDIALOG_COMMON_BUTTON_RETURN_ID.IDOK;
            else if(result == TaskDialogResult.Retry)
                id = (int)TaskDialogNativeMethods.TASKDIALOG_COMMON_BUTTON_RETURN_ID.IDRETRY;
            else if(result == TaskDialogResult.Yes)
                id = (int)TaskDialogNativeMethods.TASKDIALOG_COMMON_BUTTON_RETURN_ID.IDYES;

            SendMessageHelper(TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_CLICK_BUTTON, id, 0);
        }

        #region Main Dialog Proc

        private int DialogProc(
            IntPtr hwnd,
            uint msg,
            IntPtr wParam,
            IntPtr lParam,
            IntPtr lpRefData)
        {
            // Fetch the HWND - it may be the first time we're getting it.
            hWndDialog = hwnd;

            // Big switch on the various notifications the 
            // dialog proc can get.
            switch ((TaskDialogNativeMethods.TASKDIALOG_NOTIFICATIONS)msg)
            {
                case TaskDialogNativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_CREATED:
                    int result = PerformDialogInitialization();
                    outerDialog.RaiseOpenedEvent();
                    return result;
                case TaskDialogNativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_BUTTON_CLICKED:
                    return HandleButtonClick((int)wParam);
                case TaskDialogNativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_RADIO_BUTTON_CLICKED:
                    return HandleRadioButtonClick((int)wParam);
                case TaskDialogNativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_HYPERLINK_CLICKED:
                    return HandleHyperlinkClick(lParam);
                case TaskDialogNativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_HELP:
                    return HandleHelpInvocation();
                case TaskDialogNativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_TIMER:
                    return HandleTick((int)wParam);
                case TaskDialogNativeMethods.TASKDIALOG_NOTIFICATIONS.TDN_DESTROYED:
                    return PerformDialogCleanup();
                default:
                    break;
            }
            return (int)HRESULT.S_OK;
        }


        // Once the task dialog HWND is open, we need to send 
        // additional messages to configure it.
        private int PerformDialogInitialization()
        {
            // Initialize Progress or Marquee Bar.
            if (IsOptionSet(TaskDialogNativeMethods.TASKDIALOG_FLAGS.TDF_SHOW_PROGRESS_BAR))
            {
                UpdateProgressBarRange();
                
                // The order of the following is important - 
                // state is more important than value, 
                // and non-normal states turn off the bar value change 
                // animation, which is likely the intended
                // and preferable behavior.
                UpdateProgressBarState(settings.ProgressBarState);
                UpdateProgressBarValue(settings.ProgressBarValue);
                
                // Due to a bug that wasn't fixed in time for RTM of Vista,
                // second SendMessage is required if the state is non-Normal.
                UpdateProgressBarValue(settings.ProgressBarValue);
            }
            else if (IsOptionSet(TaskDialogNativeMethods.TASKDIALOG_FLAGS.TDF_SHOW_MARQUEE_PROGRESS_BAR))
            {
                // TDM_SET_PROGRESS_BAR_MARQUEE is necessary 
                // to cause the marquee to start animating.
                // Note that this internal task dialog setting is 
                // round-tripped when the marquee is
                // is set to different states, so it never has to 
                // be touched/sent again.
                SendMessageHelper(TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_PROGRESS_BAR_MARQUEE, 1, 0);
                UpdateProgressBarState(settings.ProgressBarState);
            }

            if (settings.ElevatedButtons != null && settings.ElevatedButtons.Count > 0)
            {
                foreach (int id in settings.ElevatedButtons)
                {
                    UpdateElevationIcon(id, true);
                }
            }
            
            return CoreErrorHelper.IGNORED;
        }

        private int HandleButtonClick(int id)
        {
            // First we raise a Click event, if there is a custom button
            // However, we implement Close() by sending a cancel button, so 
            // we don't want to raise a click event in response to that.
            if (showState != DialogShowState.Closing)
                outerDialog.RaiseButtonClickEvent(id);

            // Once that returns, we raise a Closing event for the dialog
            // The Win32 API handles button clicking-and-closing 
            // as an atomic action,
            // but it is more .NET friendly to split them up.
            // Unfortunately, we do NOT have the return values at this stage.
            if(id <= 9)
                return outerDialog.RaiseClosingEvent(id);
            else
                return 1;
        }

        private int HandleRadioButtonClick(int id)
        {
            // When the dialog sets the radio button to default, 
            // it (somewhat confusingly)issues a radio button clicked event
            //  - we mask that out - though ONLY if
            // we do have a default radio button
            if (firstRadioButtonClicked && !IsOptionSet(TaskDialogNativeMethods.TASKDIALOG_FLAGS.TDF_NO_DEFAULT_RADIO_BUTTON))
                firstRadioButtonClicked = false;
            else
            {
                outerDialog.RaiseButtonClickEvent(id);
            }

            // Note: we don't raise Closing, as radio 
            // buttons are non-committing buttons
            return CoreErrorHelper.IGNORED;
        }

        private int HandleHyperlinkClick(IntPtr pszHREF)
        {
            string link = Marshal.PtrToStringUni(pszHREF);
            outerDialog.RaiseHyperlinkClickEvent(link);

            return CoreErrorHelper.IGNORED;
        }


        private int HandleTick(int ticks)
        {
            outerDialog.RaiseTickEvent(ticks);
            return CoreErrorHelper.IGNORED;
        }

        private int HandleHelpInvocation()
        {
            outerDialog.RaiseHelpInvokedEvent();
            return CoreErrorHelper.IGNORED;
        }

        // There should be little we need to do here, 
        // as the use of the NativeTaskDialog is
        // that it is instantiated for a single show, then disposed of.
        private int PerformDialogCleanup()
        {
            firstRadioButtonClicked = true;

            return CoreErrorHelper.IGNORED;
        }

        #endregion

        #region Update members

        internal void UpdateProgressBarValue(int i)
        {
            AssertCurrentlyShowing();
            SendMessageHelper(TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_PROGRESS_BAR_POS, i, 0);
        }

        internal void UpdateProgressBarRange()
        {
            AssertCurrentlyShowing();

            // Build range LPARAM - note it is in REVERSE intuitive order.
            long range = NativeTaskDialog.MakeLongLParam(
                settings.ProgressBarMaximum, 
                settings.ProgressBarMinimum);

            SendMessageHelper(TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_PROGRESS_BAR_RANGE, 0, range);
        }

        internal void UpdateProgressBarState(TaskDialogProgressBarState state)
        {
            AssertCurrentlyShowing();
            SendMessageHelper(TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_PROGRESS_BAR_STATE, (int)state, 0);
        }

        internal void UpdateText(string text)
        {
            UpdateTextCore(text, TaskDialogNativeMethods.TASKDIALOG_ELEMENTS.TDE_CONTENT);
        }

        internal void UpdateInstruction(string instruction)
        {
            UpdateTextCore(instruction, TaskDialogNativeMethods.TASKDIALOG_ELEMENTS.TDE_MAIN_INSTRUCTION);
        }

        internal void UpdateFooterText(string footerText)
        {
            UpdateTextCore(footerText, TaskDialogNativeMethods.TASKDIALOG_ELEMENTS.TDE_FOOTER);
        }

        internal void UpdateExpandedText(string expandedText)
        {
            UpdateTextCore(expandedText, TaskDialogNativeMethods.TASKDIALOG_ELEMENTS.TDE_EXPANDED_INFORMATION);
        }

        private void UpdateTextCore(string s, TaskDialogNativeMethods.TASKDIALOG_ELEMENTS element)
        {
            AssertCurrentlyShowing();

            FreeOldString(element);
            SendMessageHelper(
                TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_ELEMENT_TEXT,
                (int)element,
                (long)MakeNewString(s, element));
        }

        internal void UpdateMainIcon(TaskDialogStandardIcon mainIcon)
        {
            UpdateIconCore(mainIcon, TaskDialogNativeMethods.TASKDIALOG_ICON_ELEMENT.TDIE_ICON_MAIN);
        }

        internal void UpdateFooterIcon(TaskDialogStandardIcon footerIcon)
        {
            UpdateIconCore(footerIcon, TaskDialogNativeMethods.TASKDIALOG_ICON_ELEMENT.TDIE_ICON_FOOTER);
        }

        private void UpdateIconCore(TaskDialogStandardIcon icon, TaskDialogNativeMethods.TASKDIALOG_ICON_ELEMENT element)
        {
            AssertCurrentlyShowing();
            SendMessageHelper(
                TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ICON,
                (int)element,
                (long)icon);
        }

        internal void UpdateCheckBoxChecked(bool cbc)
        {
            AssertCurrentlyShowing();
            SendMessageHelper(
                TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_CLICK_VERIFICATION,
                (cbc ? 1 : 0),
                1);
        }

        internal void UpdateElevationIcon(int buttonId, bool showIcon)
        {
            AssertCurrentlyShowing();
            SendMessageHelper(
                TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE,
                buttonId,
                Convert.ToInt32(showIcon));
        }

        internal void UpdateButtonEnabled(int buttonID, bool enabled)
        {
            AssertCurrentlyShowing();
            SendMessageHelper(
                TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_ENABLE_BUTTON, buttonID, enabled == true ? 1 : 0);
        }
        internal void UpdateRadioButtonEnabled(int buttonID, bool enabled)
        {
            AssertCurrentlyShowing();
            SendMessageHelper(
                TaskDialogNativeMethods.TASKDIALOG_MESSAGES.TDM_ENABLE_RADIO_BUTTON, buttonID, enabled == true? 1 : 0);
        }

        internal void AssertCurrentlyShowing()
        {
            Debug.Assert(showState == DialogShowState.Showing, "Update*() methods should only be called while native dialog is showing");
        }

        #endregion

        #region Helpers

        private int SendMessageHelper(TaskDialogNativeMethods.TASKDIALOG_MESSAGES msg, int wParam, long lParam)
        {
            // Be sure to at least assert here - 
            // messages to invalid handles often just disappear silently
            Debug.Assert(hWndDialog != null, 
                "HWND for dialog is null during SendMessage");

            return (int)CoreNativeMethods.SendMessage(
                hWndDialog,
                (uint)msg,
                (IntPtr)wParam,
                new IntPtr(lParam));
        }

        private bool IsOptionSet(TaskDialogNativeMethods.TASKDIALOG_FLAGS flag)
        {
            return ((nativeDialogConfig.dwFlags & flag) == flag);
        }

        // Allocates a new string on the unmanaged heap, 
        // and stores the pointer so we can free it later.

        private IntPtr MakeNewString(string s,
            TaskDialogNativeMethods.TASKDIALOG_ELEMENTS element)
        {
            IntPtr newStringPtr = Marshal.StringToHGlobalUni(s);
            updatedStrings[(int)element] = newStringPtr;
            return newStringPtr;
        }

        // Checks to see if the given element already has an 
        // updated string, and if so, 
        // frees it. This is done in preparation for a call to 
        // MakeNewString(), to prevent
        // leaks from multiple updates calls on the same element 
        // within a single native dialog lifetime.

        private void FreeOldString(TaskDialogNativeMethods.TASKDIALOG_ELEMENTS element)
        {
            int elementIndex = (int)element;
            if (updatedStrings[elementIndex] != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(updatedStrings[elementIndex]);
                updatedStrings[elementIndex] = IntPtr.Zero;
            }
        }

        // Based on the following defines in WinDef.h and WinUser.h:
        // #define MAKELPARAM(l, h) ((LPARAM)(DWORD)MAKELONG(l, h))
        // #define MAKELONG(a, b) ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
        private static long MakeLongLParam(int a, int b)
        {
            return (a << 16) + b;
        }

        // Builds the actual configuration that the 
        // NativeTaskDialog (and underlying Win32 API)
        // expects, by parsing the various control lists, 
        // marshaling to the unmanaged heap, etc.

        private void MarshalDialogControlStructs()
        {
            if (settings.Buttons != null && settings.Buttons.Length > 0)
            {
                buttonArray = AllocateAndMarshalButtons(settings.Buttons);
                settings.NativeConfiguration.pButtons = buttonArray;
                settings.NativeConfiguration.cButtons = (uint)settings.Buttons.Length;
            }
            if (settings.RadioButtons != null && settings.RadioButtons.Length > 0)
            {
                radioButtonArray = AllocateAndMarshalButtons(settings.RadioButtons);
                settings.NativeConfiguration.pRadioButtons = radioButtonArray;
                settings.NativeConfiguration.cRadioButtons = (uint)settings.RadioButtons.Length;
            }
        }

        private static IntPtr AllocateAndMarshalButtons(TaskDialogNativeMethods.TASKDIALOG_BUTTON[] structs)
        {
            IntPtr initialPtr = Marshal.AllocHGlobal(
                Marshal.SizeOf(typeof(TaskDialogNativeMethods.TASKDIALOG_BUTTON)) * structs.Length);

            IntPtr currentPtr = initialPtr;
            foreach (TaskDialogNativeMethods.TASKDIALOG_BUTTON button in structs)
            {
                Marshal.StructureToPtr(button, currentPtr, false);
                currentPtr = (IntPtr)((int)currentPtr + Marshal.SizeOf(button));
            }

            return initialPtr;
        }

        #endregion

        #region IDispose Pattern

        private bool disposed;

        // Finalizer and IDisposable implementation.
        public void Dispose() 
        { 
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        ~NativeTaskDialog() 
        { 
            Dispose(false); 
        }

        // Core disposing logic.
        protected void Dispose(bool disposing)
        {
            if (!disposed)
            {
                disposed = true; 

                // Single biggest resource - make sure the dialog 
                // itself has been instructed to close.

                if (showState == DialogShowState.Showing)
                    NativeClose(TaskDialogResult.Cancel);
                
                // Clean up custom allocated strings that were updated
                // while the dialog was showing. Note that the strings
                // passed in the initial TaskDialogIndirect call will
                // be cleaned up automagically by the default 
                // marshalling logic.

                if (updatedStrings != null)
                {
                    for (int i = 0; i < updatedStrings.Length; i++)
                    {
                        if (updatedStrings[i] != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(updatedStrings[i]);
                            updatedStrings[i] = IntPtr.Zero;
                        }
                    }
                }

                // Clean up the button and radio button arrays, if any.
                if (buttonArray != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(buttonArray);
                    buttonArray = IntPtr.Zero;
                }
                if (radioButtonArray != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(radioButtonArray);
                    radioButtonArray = IntPtr.Zero;
                }

                if (disposing)
                {
                    // Clean up managed resources - currently there are none
                    // that are interesting.
                }
            }
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Shakeel Iqbal
Software Developer (Senior) TEO
Pakistan Pakistan
Passion and positive dedication is essential part of success. I believe on hardworking and sharing knowledge with others. I always try to be a better than I am and think positive for positive result.

My Blogs

My Linked-In Profile

You may also be interested in...

Pro
Pro
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web02 | 2.8.190114.1 | Last Updated 2 Jan 2010
Article Copyright 2010 by Shakeel Iqbal
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid