private int PrivateShow( IntPtr hwndOwner, out bool verificationFlagChecked, out int radioButtonResult )
{
verificationFlagChecked = false;
radioButtonResult = 0;
int result = 0;
VistaUnsafeNativeMethods.TASKDIALOGCONFIG config = new VistaUnsafeNativeMethods.TASKDIALOGCONFIG ( );
try {
config.cbSize = ( uint ) Marshal.SizeOf ( typeof ( VistaUnsafeNativeMethods.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 |= VistaUnsafeNativeMethods.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;
}
VistaTaskDialogButton[ ] customButtons = this.buttons;
if ( customButtons.Length > 0 ) {
// Hand marshal the buttons array.
int elementSize = Marshal.SizeOf ( typeof ( VistaTaskDialogButton ) );
config.pButtons = Marshal.AllocHGlobal ( elementSize * ( int ) customButtons.Length );
for ( int i = 0; i < customButtons.Length; i++ ) {
unsafe // Unsafe because of pointer arithmatic.
{
byte* p = ( byte* ) config.pButtons;
Marshal.StructureToPtr ( customButtons[ i ], ( IntPtr ) ( p + ( elementSize * i ) ), false );
}
config.cButtons++;
}
}
VistaTaskDialogButton[ ] customRadioButtons = this.radioButtons;
if ( customRadioButtons.Length > 0 ) {
// Hand marshal the buttons array.
int elementSize = Marshal.SizeOf ( typeof ( VistaTaskDialogButton ) );
config.pRadioButtons = Marshal.AllocHGlobal ( elementSize * ( int ) customRadioButtons.Length );
for ( int i = 0; i < customRadioButtons.Length; i++ ) {
unsafe // Unsafe because of pointer arithmatic.
{
byte* p = ( byte* ) config.pRadioButtons;
Marshal.StructureToPtr ( customRadioButtons[ i ], ( IntPtr ) ( p + ( elementSize * i ) ), false );
}
config.cRadioButtons++;
}
}
config.nDefaultButton = this.defaultButton;
config.nDefaultRadioButton = this.defaultRadioButton;
if ( !string.IsNullOrEmpty ( this.verificationText ) ) {
config.pszVerificationText = this.verificationText;
}
if ( !string.IsNullOrEmpty ( this.expandedInformation ) ) {
config.pszExpandedInformation = this.expandedInformation;
}
if ( !string.IsNullOrEmpty ( this.expandedControlText ) ) {
config.pszExpandedControlText = this.expandedControlText;
}
if ( !string.IsNullOrEmpty ( this.collapsedControlText ) ) {
config.pszCollapsedControlText = this.CollapsedControlText;
}
config.FooterIcon = ( IntPtr ) this.footerIcon;
if ( this.customFooterIcon != null ) {
config.dwFlags |= VistaUnsafeNativeMethods.TASKDIALOG_FLAGS.TDF_USE_HICON_FOOTER;
config.FooterIcon = this.customFooterIcon.Handle;
}
if ( !string.IsNullOrEmpty ( this.footer ) ) {
config.pszFooter = this.footer;
}
// If our user has asked for a callback then we need to ask for one to
// translate to the friendly version.
if ( this.callback != null ) {
config.pfCallback = new VistaUnsafeNativeMethods.VistaTaskDialogCallback ( 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.
VistaUnsafeNativeMethods.TaskDialogIndirect ( ref config, out result, out radioButtonResult, out verificationFlagChecked );
} finally {
// Free the unmanged memory needed for the button arrays.
// There is the possiblity of leaking memory if the app-domain is destroyed in a non clean way
// and the hosting OS process is kept alive but fixing this would require using hardening techniques
// that are not required for the users of this class.
if ( config.pButtons != IntPtr.Zero ) {
int elementSize = Marshal.SizeOf ( typeof ( VistaTaskDialogButton ) );
for ( int i = 0; i < config.cButtons; i++ ) {
unsafe {
byte* p = ( byte* ) config.pButtons;
Marshal.DestroyStructure ( ( IntPtr ) ( p + ( elementSize * i ) ), typeof ( VistaTaskDialogButton ) );
}
}
Marshal.FreeHGlobal ( config.pButtons );
}
if ( config.pRadioButtons != IntPtr.Zero ) {
int elementSize = Marshal.SizeOf ( typeof ( VistaTaskDialogButton ) );
for ( int i = 0; i < config.cRadioButtons; i++ ) {
unsafe {
byte* p = ( byte* ) config.pRadioButtons;
Marshal.DestroyStructure ( ( IntPtr ) ( p + ( elementSize * i ) ), typeof ( VistaTaskDialogButton ) );
}
}
Marshal.FreeHGlobal ( config.pRadioButtons );
}
}
return result;
}