in sources/Google.Solutions.Mvvm/Controls/TaskDialog.cs [54:199]
public DialogResult ShowDialog(
IWin32Window? parent,
TaskDialogParameters parameters)
{
parameters.ExpectNotNull(nameof(parameters));
if (!parameters.Buttons.Any())
{
throw new InvalidOperationException
("The dialog must contain at least one button");
}
var standardButtons = parameters.Buttons
.OfType<TaskDialogStandardButton>()
.ToList();
var commandButtons = parameters.Buttons
.OfType<TaskDialogCommandLinkButton>()
.ToList();
Precondition.Expect(
standardButtons.Any(),
"At least one standard button is required");
using (var commandButtonsHandle = LocalAllocSafeHandle.LocalAlloc(
(uint)(Marshal.SizeOf<TASKDIALOG_BUTTON_RAW>() * commandButtons.Count)))
{
//
// Prepare native struct for command buttons.
//
var commandButtonTexts = commandButtons
.Select(b =>
{
//
// Text up to the first new line character is treated as the
// command link's main text, the remainder is treated as the
// command link's note.
//
var text = b.Text.Replace('\n', ' ');
if (b.Details != null)
{
text += $"\n{b.Details}";
}
return text;
})
.Select(text => Marshal.StringToHGlobalUni(text))
.ToArray();
for (var i = 0; i < commandButtons.Count; i++)
{
Marshal.StructureToPtr(
new TASKDIALOG_BUTTON_RAW()
{
//
// Add ID offset to avoid conflict with IDOK/IDCANCEL.
//
nButtonID = CommandLinkIdOffset + i,
pszButtonText = commandButtonTexts[i]
},
commandButtonsHandle.DangerousGetHandle() + i * Marshal.SizeOf<TASKDIALOG_BUTTON_RAW>(),
false);
}
try
{
var flags =
TASKDIALOG_FLAGS.TDF_EXPAND_FOOTER_AREA |
TASKDIALOG_FLAGS.TDF_ENABLE_HYPERLINKS;
if (commandButtons.Count != 0)
{
flags |= TASKDIALOG_FLAGS.TDF_USE_COMMAND_LINKS;
}
var config = new TASKDIALOGCONFIG()
{
cbSize = (uint)Marshal.SizeOf<TASKDIALOGCONFIG>(),
hwndParent = parent?.Handle ?? IntPtr.Zero,
dwFlags = flags,
dwCommonButtons = standardButtons
.Select(b => b.Flag)
.Aggregate((f1, f2) => f1 | f2),
pszWindowTitle = parameters.Caption,
MainIcon = parameters.Icon?.Handle ?? IntPtr.Zero,
pszMainInstruction = parameters.Heading,
pszContent = parameters.Text,
pButtons = commandButtons.Count != 0
? commandButtonsHandle.DangerousGetHandle()
: IntPtr.Zero,
cButtons = (uint)commandButtons.Count,
pszExpandedInformation = parameters.Footnote,
pszVerificationText = parameters.VerificationCheckBox?.Text,
pfCallback = (hwnd, notification, wParam, lParam, refData) =>
{
if (notification == TASKDIALOG_NOTIFICATIONS.TDN_HYPERLINK_CLICKED)
{
parameters.PerformLinkClick();
}
return HRESULT.S_OK;
}
};
var function = this.TaskDialogIndirect ?? NativeMethods.TaskDialogIndirect;
function(
ref config,
out var buttonIdPressed,
out var _,
out var verificationFlagPressed);
if (parameters.VerificationCheckBox != null)
{
parameters.VerificationCheckBox.Checked = verificationFlagPressed;
}
//
// Map the result back to the right button.
//
if (buttonIdPressed >= CommandLinkIdOffset &&
buttonIdPressed < CommandLinkIdOffset + commandButtons.Count)
{
var pressedCommandButton = commandButtons[buttonIdPressed - CommandLinkIdOffset];
pressedCommandButton.PerformClick();
return pressedCommandButton.Result;
}
else if (standardButtons.FirstOrDefault(b => b.CommandId == buttonIdPressed)
is var pressedStandardButton &&
pressedStandardButton != null)
{
return pressedStandardButton.Result;
}
else
{
throw new InvalidOperationException(
$"The TaskDialog returned an unexpected result: {buttonIdPressed}");
}
}
finally
{
foreach (var commandButtonText in commandButtonTexts)
{
Marshal.FreeHGlobal(commandButtonText);
}
}
}
}