visual-c++mfctaskdialog

Using CTaskDialog with hyperlinks is messing up multiline command buttons


I am trying to show a task dialog:

CMeetingScheduleAssistantDlg::ScheduleCheckResult 
CMeetingScheduleAssistantDlg::ShowResultsInTaskDialog(
    const CString& content,
    const bool showUpgradeOption,
    const bool showRequestDataOption)
{
    CTaskDialog taskDlg(
        content,
        L"Meeting Workbook Data Status",
        L"Check for Latest Schedule Information",
        TDCBF_CLOSE_BUTTON);
        // , TDF_ENABLE_HYPERLINKS | TDF_ALLOW_DIALOG_CANCELLATION);

    taskDlg.SetMainIcon(TD_INFORMATION_ICON);

    // Add command link buttons
    if (showUpgradeOption)
    {
        taskDlg.AddCommandControl(
            static_cast<int>(ScheduleCheckResult::Upgrade),
            L"Upgrade Software\nDownload and install the latest version with new features");
    }
    else if (showRequestDataOption)
    {
        taskDlg.AddCommandControl(
            static_cast<int>(ScheduleCheckResult::RequestData),
            L"Request Data\nSend an email to get the most recent Meeting Workbook data");
    }

    // Set dialog width
    taskDlg.SetDialogWidth(CMeetingScheduleAssistantApp::DetectMessageBoxWidth());

    // Add footer
    if (showRequestDataOption)
    {
        taskDlg.SetFooterText(L"Make sure your email settings are correctly configured before submitting a data request.");
        // taskDlg.SetFooterText(L"Make sure your <a href=\"https://www.publictalksoftware.co.uk/help-msa/msa-options-email.html\">email settings</a> are correctly configured before submitting a data request.");
        taskDlg.SetFooterIcon(TD_INFORMATION_ICON);
    }

    // Show dialog and return result
    const auto result = taskDlg.DoModal();
    return static_cast<CMeetingScheduleAssistantDlg::ScheduleCheckResult>(result);
}

It works fine:

Sample

But I have a couple of issues when I try to use either of the TDF_ENABLE_HYPERLINKS | TDF_ALLOW_DIALOG_CANCELLATION options. The footer will show correctly with the hyperlink but the multiline button is messed up.

It seems I can only have one way or the other.

Side point: \t does not expand in the content area.

Update

This article implies it is possible. https://www.nuonsoft.com/blog/2009/06/10/ctaskdialog-in-mfc-in-visual-c-2010/

sample

So, maybe the reason it is not working is because I am using version of the task dialog that supports dark mode via Microsoft Detours. Will investigate …

Update 2

It has nothing to do with Microsoft Detours because the normal dialog does the same:

normal task dialog


Solution

  • I downloaded the sample in the article that I referred to and it worked. So I decided to examine how it coded the task dialog.

    I noticed:

    // Enable support for hyperlinks and a timer
    int options = taskDlg.GetOptions();
    options |= TDF_ENABLE_HYPERLINKS;
    options |= TDF_CALLBACK_TIMER;
    taskDlg.SetOptions(options);
    

    So, I decided to change how I was setting the options in my code:

    CMeetingScheduleAssistantDlg::ScheduleCheckResult 
    CMeetingScheduleAssistantDlg::ShowResultsInTaskDialog(
        const CString& content,
        const bool showUpgradeOption,
        const bool showRequestDataOption)
    {
        CTaskDialog taskDlg(
            content,
            L"Meeting Workbook Data Status",
            L"Check for Latest Schedule Information",
            TDCBF_CLOSE_BUTTON);
    
        // Enable support for hyperlinks and the close icon
        int options = taskDlg.GetOptions();
        options |= TDF_ENABLE_HYPERLINKS;
        options |= TDF_ALLOW_DIALOG_CANCELLATION;
        taskDlg.SetOptions(options);
    
        taskDlg.SetMainIcon(TD_INFORMATION_ICON);
    
        // Add command link buttons
        if (showUpgradeOption)
        {
            taskDlg.AddCommandControl(
                static_cast<int>(ScheduleCheckResult::Upgrade),
                L"Upgrade Software\nDownload and install the latest version with new features");
        }
        else if (showRequestDataOption)
        {
            taskDlg.AddCommandControl(
                static_cast<int>(ScheduleCheckResult::RequestData),
                L"Request Data\nSend an email to get the most recent Meeting Workbook data");
        }
    
        // Set dialog width
        taskDlg.SetDialogWidth(CMeetingScheduleAssistantApp::DetectMessageBoxWidth());
    
        // Add footer
        if (showRequestDataOption)
        {
            taskDlg.SetFooterText(L"Make sure your <a href=\"https://www.publictalksoftware.co.uk/help-msa/msa-options-email.html\">email settings</a> are correctly configured before submitting a data request.");
            taskDlg.SetFooterIcon(TD_INFORMATION_ICON);
        }
    
        // Show dialog and return result
        const auto result = taskDlg.DoModal();
        return static_cast<CMeetingScheduleAssistantDlg::ScheduleCheckResult>(result);
    }
    

    And, voila:

    Correct task dialog

    Root Cause

    I examined the MFC source for the CTaskDialog constructor:

    CTaskDialog(_In_ const CString& strContent, _In_ const CString& strMainInstruction, _In_ const CString& strTitle,
        _In_ int nCommonButtons = TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON, _In_ int nTaskDialogOptions = TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS,
        _In_ const CString& strFooter = CString());
    
    CTaskDialog(_In_ const CString& strContent, _In_ const CString& strMainInstruction, _In_ const CString& strTitle,
        _In_ int nIDCommandControlsFirst, _In_ int nIDCommandControlsLast, _In_ int nCommonButtons,
        _In_ int nTaskDialogOptions = TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS, _In_ const CString& strFooter = CString());
    

    I noticed the user of an extra option. So this code is fine:

    CTaskDialog taskDlg(
        content,
        strHeading,
        strTitle,
        TDCBF_CLOSE_BUTTON,
        TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS | TDF_ALLOW_DIALOG_CANCELLATION);