/// <summary> /// The callback from the native Task Dialog. This prepares the friendlier arguments and calls the simplier callback. /// </summary> /// <param name="hwnd">The window handle of the Task Dialog that is active.</param> /// <param name="msg">The notification. A TaskDialogNotification value.</param> /// <param name="wparam">Specifies additional noitification information. The contents of this parameter depends on the value of the msg parameter.</param> /// <param name="lparam">Specifies additional noitification information. The contents of this parameter depends on the value of the msg parameter.</param> /// <param name="refData">Specifies the application-defined value given in the call to TaskDialogIndirect.</param> /// <returns>A HRESULT. It's not clear in the spec what a failed result will do.</returns> private int PrivateCallback([In] IntPtr hwnd, [In] uint msg, [In] UIntPtr wparam, [In] IntPtr lparam, [In] IntPtr refData) { TaskDialogCallback callback = this.callback; if (callback != null) { // Prepare arguments for the callback to the user we are insulating from Interop casting sillyness. // Future: Consider reusing a single ActiveTaskDialog object and mark it as destroyed on the destry notification. VistaActiveTaskDialog activeDialog = new VistaActiveTaskDialog(hwnd); VistaTaskDialogNotificationArgs args = new VistaTaskDialogNotificationArgs(); args.Config = this.config; args.Notification = (VistaTaskDialogNotification)msg; switch (args.Notification) { case VistaTaskDialogNotification.ButtonClicked: case VistaTaskDialogNotification.RadioButtonClicked: args.ButtonId = (int)wparam; // The index, ideally, should be -1 or something whenever the //dialog was closed by non-common-button means such as Alt+F4 //or using the Close action on the System menu or the red X // I can, with little trouble, detect this for the emulated dialog, //however the native dialog gives me no indication and in fact //simply reports a buttonId of 2 (Cancel) regardless of whether //the actual Cancel button was used or one of the above alt methods. // If I could hook into the native dialogs messages and detect: // WM_SYSCOMMAND with WParam of SC_CLOSE // ...then I could tell for sure, but I'm not sure how to listen //in on its messages. My Win32-fu not good enough. // For now, I will have the emulated dialog simply pretend like it //cannot tell either until I can figure out a way to determine it //with the native dialog, too. if (args.ButtonId > 100) args.ButtonIndex = args.ButtonId % 500; else args.ButtonIndex = TaskDialog.GetButtonIndexForCommonButton(args.Config.CommonButtons, args.ButtonId); break; case VistaTaskDialogNotification.HyperlinkClicked: args.Hyperlink = Marshal.PtrToStringUni(lparam); break; case VistaTaskDialogNotification.Timer: args.TimerTickCount = (uint)wparam; break; case VistaTaskDialogNotification.VerificationClicked: args.VerificationFlagChecked = (wparam != UIntPtr.Zero); break; case VistaTaskDialogNotification.ExpandoButtonClicked: args.Expanded = (wparam != UIntPtr.Zero); break; } bool result = callback(activeDialog, args, this.callbackData); return (result ? 1 : 0); } return 0; // false; }
/// <summary> /// The callback from the native Task Dialog. This prepares the friendlier arguments and calls the simplier callback. /// </summary> /// <param name="hwnd">The window handle of the Task Dialog that is active.</param> /// <param name="msg">The notification. A TaskDialogNotification value.</param> /// <param name="wparam">Specifies additional noitification information. The contents of this parameter depends on the value of the msg parameter.</param> /// <param name="lparam">Specifies additional noitification information. The contents of this parameter depends on the value of the msg parameter.</param> /// <param name="refData">Specifies the application-defined value given in the call to TaskDialogIndirect.</param> /// <returns>A HRESULT. It's not clear in the spec what a failed result will do.</returns> private int PrivateCallback([In] IntPtr hwnd, [In] uint msg, [In] UIntPtr wparam, [In] IntPtr lparam, [In] IntPtr refData) { TaskDialogCallback callback = this.callback; if (callback != null) { // Prepare arguments for the callback to the user we are insulating from Interop casting sillyness. // Future: Consider reusing a single ActiveTaskDialog object and mark it as destroyed on the destry notification. VistaActiveTaskDialog activeDialog = new VistaActiveTaskDialog(hwnd); VistaTaskDialogNotificationArgs args = new VistaTaskDialogNotificationArgs(); args.Config = this.config; args.Notification = (VistaTaskDialogNotification)msg; switch (args.Notification) { case VistaTaskDialogNotification.ButtonClicked: case VistaTaskDialogNotification.RadioButtonClicked: args.ButtonId = (int)wparam; break; case VistaTaskDialogNotification.HyperlinkClicked: args.Hyperlink = Marshal.PtrToStringUni(lparam); break; case VistaTaskDialogNotification.Timer: args.TimerTickCount = (uint)wparam; break; case VistaTaskDialogNotification.VerificationClicked: args.VerificationFlagChecked = (wparam != UIntPtr.Zero); break; case VistaTaskDialogNotification.ExpandoButtonClicked: args.Expanded = (wparam != UIntPtr.Zero); break; } bool result = callback(activeDialog, args, this.callbackData); return (result ? 1 : 0); } return 0; // false; }