//------------------------------------------------------------------ // // A P/Invoke wrapper for TaskDialog. Usability was given preference to perf and size. // // // //------------------------------------------------------------------ namespace ProcessHacker.Components { using System; using System.Drawing; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis; /// /// The active Task Dialog window. Provides several methods for acting on the active TaskDialog. /// You should not use this object after the TaskDialog Destroy notification callback. Doing so /// will result in undefined behavior and likely crash. /// public class ActiveTaskDialog : IWin32Window { /// /// The Task Dialog's window handle. /// private IntPtr handle; /// /// Creates a ActiveTaskDialog. /// /// The Task Dialog's window handle. internal ActiveTaskDialog(IntPtr handle) { if (handle == IntPtr.Zero) { throw new ArgumentNullException("handle"); } this.handle = handle; } /// /// The Task Dialog's handle. /// We don't own this window. /// public IntPtr Handle { get { return this.handle; } } /// /// Refreshes the contents of the Task Dialog. /// Clients may send this message to the task dialog to /// dynamically change the task dialog contents at run time. /// public void NavigatePage() { //TODO: complete TaskDialog Navigate Page //IntPtr* p = (IntPtr*)UnsafeNativeMethods.TASKDIALOGCONFIG(); //UnsafeNativeMethods.SendMessage( // this.Handle, // (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_NAVIGATE_PAGE, // IntPtr.Zero, // config); } /// /// Simulate the action of a button click in the TaskDialog. This can be a DialogResult value /// or the ButtonID set on a TasDialogButton set on TaskDialog.Buttons. /// /// Indicates the button ID to be selected. /// If the function succeeds the return value is true. public bool ClickButton(int buttonId) { // TDM_CLICK_BUTTON = WM_USER+102, // wParam = Button ID return UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_CLICK_BUTTON, (IntPtr)buttonId, IntPtr.Zero) != IntPtr.Zero; } /// /// Used to indicate whether the hosted progress bar should be displayed in marquee mode or not. /// /// Specifies whether the progress bar sbould be shown in Marquee mode. /// A value of true turns on Marquee mode. /// If the function succeeds the return value is true. public bool SetMarqueeProgressBar(bool marquee) { // TDM_SET_MARQUEE_PROGRESS_BAR = WM_USER+103, // wParam = 0 (nonMarque) wParam != 0 (Marquee) return UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_MARQUEE_PROGRESS_BAR, (marquee ? (IntPtr)1 : IntPtr.Zero), IntPtr.Zero) != IntPtr.Zero; // Future: get more detailed error from and throw. } /// /// Sets the state of the progress bar. /// /// The state to set the progress bar. /// If the function succeeds the return value is true. public bool SetProgressBarState(ProgressBarState newState) { // TDM_SET_PROGRESS_BAR_STATE = WM_USER+104, // wParam = new progress state return UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_PROGRESS_BAR_STATE, (IntPtr)newState, IntPtr.Zero) != IntPtr.Zero; // Future: get more detailed error from and throw. } /// /// Set the minimum and maximum values for the hosted progress bar. /// /// Minimum range value. By default, the minimum value is zero. /// Maximum range value. By default, the maximum value is 100. /// If the function succeeds the return value is true. public bool SetProgressBarRange(Int16 minRange, Int16 maxRange) { // TDM_SET_PROGRESS_BAR_RANGE = WM_USER+105, // lParam = MAKELPARAM(nMinRange, nMaxRange) // #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)) IntPtr lparam = (IntPtr)((((Int32)minRange) & 0xffff) | ((((Int32)maxRange) & 0xffff) << 16)); return UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_PROGRESS_BAR_RANGE, IntPtr.Zero, lparam) != IntPtr.Zero; // Return value is actually prior range. } /// /// Set the current position for a progress bar. /// /// The new position. /// Returns the previous value if successful, or zero otherwise. public int SetProgressBarPosition(int newPosition) { // TDM_SET_PROGRESS_BAR_POS = WM_USER+106, // wParam = new position return (int)UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_PROGRESS_BAR_POS, (IntPtr)newPosition, IntPtr.Zero); } /// /// Sets the animation state of the Marquee Progress Bar. /// /// true starts the marquee animation and false stops it. /// The time in milliseconds between refreshes. public void SetProgressBarMarquee(bool startMarquee, uint speed) { // TDM_SET_PROGRESS_BAR_MARQUEE = WM_USER+107, // wParam = 0 (stop marquee), wParam != 0 (start marquee), lparam = speed (milliseconds between repaints) UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_PROGRESS_BAR_MARQUEE, (startMarquee ? new IntPtr(1) : IntPtr.Zero), (IntPtr)speed); } /// /// Updates the content text. /// /// The new value. /// If the function succeeds the return value is true. public bool SetContent(string content) { // TDE_CONTENT, // TDM_SET_ELEMENT_TEXT = WM_USER+108 // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR) return UnsafeNativeMethods.SendMessageWithString( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_ELEMENT_TEXT, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ELEMENTS.TDE_CONTENT, content) != IntPtr.Zero; } /// /// Updates the Expanded Information text. /// /// The new value. /// If the function succeeds the return value is true. public bool SetExpandedInformation(string expandedInformation) { // TDE_EXPANDED_INFORMATION, // TDM_SET_ELEMENT_TEXT = WM_USER+108 // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR) return UnsafeNativeMethods.SendMessageWithString( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_ELEMENT_TEXT, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ELEMENTS.TDE_EXPANDED_INFORMATION, expandedInformation) != IntPtr.Zero; } /// /// Updates the Footer text. /// /// The new value. /// If the function succeeds the return value is true. public bool SetFooter(string footer) { // TDE_FOOTER, // TDM_SET_ELEMENT_TEXT = WM_USER+108 // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR) return UnsafeNativeMethods.SendMessageWithString( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_ELEMENT_TEXT, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ELEMENTS.TDE_FOOTER, footer) != IntPtr.Zero; } /// /// Updates the Main Instruction. /// /// The new value. /// If the function succeeds the return value is true. public bool SetMainInstruction(string mainInstruction) { // TDE_MAIN_INSTRUCTION // TDM_SET_ELEMENT_TEXT = WM_USER+108 // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR) return UnsafeNativeMethods.SendMessageWithString( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_ELEMENT_TEXT, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ELEMENTS.TDE_MAIN_INSTRUCTION, mainInstruction) != IntPtr.Zero; } /// /// Simulate the action of a radio button click in the TaskDialog. /// The passed buttonID is the ButtonID set on a TaskDialogButton set on TaskDialog.RadioButtons. /// /// Indicates the button ID to be selected. public void ClickRadioButton(int buttonId) { // TDM_CLICK_RADIO_BUTTON = WM_USER+110, // wParam = Radio Button ID UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_CLICK_RADIO_BUTTON, (IntPtr)buttonId, IntPtr.Zero); } /// /// Enable or disable a button in the TaskDialog. /// The passed buttonID is the ButtonID set on a TaskDialogButton set on TaskDialog.Buttons /// or a common button ID. /// /// Indicates the button ID to be enabled or diabled. /// Enambe the button if true. Disable the button if false. public void EnableButton(int buttonId, bool enable) { // TDM_ENABLE_BUTTON = WM_USER+111, // lParam = 0 (disable), lParam != 0 (enable), wParam = Button ID UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_ENABLE_BUTTON, (IntPtr)buttonId, (IntPtr)(enable ? 1 : 0)); } /// /// Enable or disable a radio button in the TaskDialog. /// The passed buttonID is the ButtonID set on a TaskDialogButton set on TaskDialog.RadioButtons. /// /// Indicates the button ID to be enabled or diabled. /// Enambe the button if true. Disable the button if false. public void EnableRadioButton(int buttonId, bool enable) { // TDM_ENABLE_RADIO_BUTTON = WM_USER+112, // lParam = 0 (disable), lParam != 0 (enable), wParam = Radio Button ID UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_ENABLE_RADIO_BUTTON, (IntPtr)buttonId, (IntPtr)(enable ? 1 : 0)); } /// /// Check or uncheck the verification checkbox in the TaskDialog. /// /// The checked state to set the verification checkbox. /// True to set the keyboard focus to the checkbox, and fasle otherwise. public void ClickVerification(bool checkedState, bool setKeyboardFocusToCheckBox) { // TDM_CLICK_VERIFICATION = WM_USER+113, // wParam = 0 (unchecked), 1 (checked), lParam = 1 (set key focus) UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_CLICK_VERIFICATION, (checkedState ? new IntPtr(1) : IntPtr.Zero), (setKeyboardFocusToCheckBox ? new IntPtr(1) : IntPtr.Zero)); } /// /// Updates the content text. /// /// The new value. public void UpdateContent(string content) { // TDE_CONTENT, // TDM_UPDATE_ELEMENT_TEXT = WM_USER+114, // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR) UnsafeNativeMethods.SendMessageWithString( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ELEMENT_TEXT, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ELEMENTS.TDE_CONTENT, content); } /// /// Updates the Expanded Information text. No effect if it was previously set to null. /// /// The new value. public void UpdateExpandedInformation(string expandedInformation) { // TDE_EXPANDED_INFORMATION, // TDM_UPDATE_ELEMENT_TEXT = WM_USER+114, // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR) UnsafeNativeMethods.SendMessageWithString( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ELEMENT_TEXT, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ELEMENTS.TDE_EXPANDED_INFORMATION, expandedInformation); } /// /// Updates the Footer text. No Effect if it was perviously set to null. /// /// The new value. public void UpdateFooter(string footer) { // TDE_FOOTER, // TDM_UPDATE_ELEMENT_TEXT = WM_USER+114, // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR) UnsafeNativeMethods.SendMessageWithString( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ELEMENT_TEXT, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ELEMENTS.TDE_FOOTER, footer); } /// /// Updates the Main Instruction. /// /// The new value. public void UpdateMainInstruction(string mainInstruction) { // TDE_MAIN_INSTRUCTION // TDM_UPDATE_ELEMENT_TEXT = WM_USER+114, // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR) UnsafeNativeMethods.SendMessageWithString( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ELEMENT_TEXT, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ELEMENTS.TDE_MAIN_INSTRUCTION, mainInstruction); } /// /// Designate whether a given Task Dialog button or command link should have a User Account Control (UAC) shield icon. /// /// ID of the push button or command link to be updated. /// False to designate that the action invoked by the button does not require elevation; /// true to designate that the action does require elevation. public void SetButtonElevationRequiredState(int buttonId, bool elevationRequired) { // TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE = WM_USER+115, // wParam = Button ID, lParam = 0 (elevation not required), lParam != 0 (elevation required) UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, (IntPtr)buttonId, (IntPtr)(elevationRequired ? new IntPtr(1) : IntPtr.Zero)); } /// /// Updates the main instruction icon. Note the type (standard via enum or /// custom via Icon type) must be used when upating the icon. /// /// Task Dialog standard icon. public void UpdateMainIcon(TaskDialogIcon icon) { // TDM_UPDATE_ICON = WM_USER+116 // wParam = icon element (TASKDIALOG_ICON_ELEMENTS), lParam = new icon (hIcon if TDF_USE_HICON_* was set, PCWSTR otherwise) UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ICON, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_MAIN, (IntPtr)icon); } /// /// Updates the main instruction icon. Note the type (standard via enum or /// custom via Icon type) must be used when upating the icon. /// /// The icon to set. public void UpdateMainIcon(Icon icon) { // TDM_UPDATE_ICON = WM_USER+116 // wParam = icon element (TASKDIALOG_ICON_ELEMENTS), lParam = new icon (hIcon if TDF_USE_HICON_* was set, PCWSTR otherwise) UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ICON, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_MAIN, (icon == null ? IntPtr.Zero : icon.Handle)); } /// /// Updates the footer icon. Note the type (standard via enum or /// custom via Icon type) must be used when upating the icon. /// /// Task Dialog standard icon. public void UpdateFooterIcon(TaskDialogIcon icon) { // TDM_UPDATE_ICON = WM_USER+116 // wParam = icon element (TASKDIALOG_ICON_ELEMENTS), lParam = new icon (hIcon if TDF_USE_HICON_* was set, PCWSTR otherwise) UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ICON, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_FOOTER, (IntPtr)icon); } /// /// Updates the footer icon. Note the type (standard via enum or /// custom via Icon type) must be used when upating the icon. /// /// The icon to set. public void UpdateFooterIcon(Icon icon) { // TDM_UPDATE_ICON = WM_USER+116 // wParam = icon element (TASKDIALOG_ICON_ELEMENTS), lParam = new icon (hIcon if TDF_USE_HICON_* was set, PCWSTR otherwise) UnsafeNativeMethods.SendMessage( this.handle, (uint)UnsafeNativeMethods.TASKDIALOG_MESSAGES.TDM_UPDATE_ICON, (IntPtr)UnsafeNativeMethods.TASKDIALOG_ICON_ELEMENTS.TDIE_ICON_FOOTER, (icon == null ? IntPtr.Zero : icon.Handle)); } } }