Search code examples
visual-c++mfctaskdialog

Exception when using TaskDialogIndirect in MFC


I am trying the following code because I want to use the Verification Check box feature:

const HICON hQuestionIcon = AfxGetApp()->LoadStandardIcon(IDI_QUESTION);
CString strTitle = CString();
CString strMainInstruction = CString();
CString strContent = CString();
CString strAdditional = CString();
CString strFooter = CString();
CString strExpand = CString();
CString strCollapse = CString();

ENSURE(strTitle.LoadString(AFX_IDS_APP_TITLE));
ENSURE(strMainInstruction.LoadString(IDS_STR_SUBMIT_STATS_MAIN_TEXT));
ENSURE(strContent.LoadString(IDS_STR_SUBMIT_STATS_CONTENT_TEXT));
ENSURE(strAdditional.LoadString(IDS_STR_SUBMIT_STATS_ADDITIONAL_TEXT));
ENSURE(strFooter.LoadString(IDS_STR_TASK_DIALOG_FOOTER));
ENSURE(strExpand.LoadString(IDS_STR_FIND_OUT_MORE));
ENSURE(strCollapse.LoadString(IDS_STR_COLLAPSE));

TASKDIALOGCONFIG sConfig = { 0 };
sConfig.cbSize = sizeof(TASKDIALOGCONFIG);
sConfig.hInstance = AfxGetResourceHandle();
sConfig.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON;
sConfig.hMainIcon = hQuestionIcon;
sConfig.pszMainInstruction = strMainInstruction.GetString();
sConfig.pszContent = strContent.GetString();
sConfig.pszExpandedControlText = strAdditional.GetString();
sConfig.pszFooter = strFooter.GetString();
sConfig.pszCollapsedControlText = strExpand.GetString();
sConfig.pszExpandedControlText = strCollapse.GetString();
sConfig.pszFooterIcon = TD_INFORMATION_ICON;
sConfig.pszVerificationText = _T("Stop displaying this message");
sConfig.cxWidth = CMeetingScheduleAssistantApp::DetectMessageBoxWidth();

int iButtonPressed = IDNO; // Default
BOOL bStopDisplayingMessage = FALSE;

TaskDialogIndirect(&sConfig, &iButtonPressed, NULL, &bStopDisplayingMessage);

if (bStopDisplayingMessage)
{
    CChristianLifeMinistryUtils::HidePromptToSubmitWorkbookDownloadStats();
}

return iButtonPressed;

But I am getting an exception:

enter image description here

I can do a regular CTaskDialog instead (without checkbox) and it is fine.


Solution

  • Whilst there are other problems with the code I showed you in the question, the resolution to the exception was setting the parent:

    sConfig.hwndParent = GetSafeHwnd();
    

    It is not disussed or mentioned here. I found it out by viewing the source. The TASKDIALOGCONFIG topic says it can be NULL though.

    Either way, exception doesn't happen now.


    Complete Code

    const HICON hQuestionIcon = AfxGetApp()->LoadStandardIcon(IDI_QUESTION);
    CString strTitle;
    CString strMainInstruction;
    CString strContent;
    CString strAdditional;
    CString strFooter;
    CString strExpand;
    CString strCollapse;
    
    ENSURE(strTitle.LoadString(AFX_IDS_APP_TITLE));
    ENSURE(strMainInstruction.LoadString(IDS_STR_SUBMIT_STATS_MAIN_TEXT));
    ENSURE(strContent.LoadString(IDS_STR_SUBMIT_STATS_CONTENT_TEXT));
    ENSURE(strAdditional.LoadString(IDS_STR_SUBMIT_STATS_ADDITIONAL_TEXT));
    ENSURE(strFooter.LoadString(IDS_STR_TASK_DIALOG_FOOTER));
    ENSURE(strExpand.LoadString(IDS_STR_FIND_OUT_MORE));
    ENSURE(strCollapse.LoadString(IDS_STR_COLLAPSE));
    
    TASKDIALOGCONFIG sConfig = { 0 };
    sConfig.hwndParent = GetSafeHwnd();
    sConfig.cbSize = sizeof(TASKDIALOGCONFIG);
    sConfig.dwFlags = TDF_ENABLE_HYPERLINKS | TDF_USE_HICON_MAIN;
    sConfig.hInstance = AfxGetResourceHandle();
    sConfig.dwCommonButtons = TDCBF_YES_BUTTON | TDCBF_NO_BUTTON;
    sConfig.hMainIcon = hQuestionIcon;
    sConfig.pszMainInstruction = strMainInstruction.GetString();
    sConfig.pszContent = strContent.GetString();
    sConfig.pszExpandedInformation = strAdditional.GetString();
    sConfig.pszFooter = strFooter.GetString();
    sConfig.pszCollapsedControlText = strExpand.GetString();
    sConfig.pszExpandedControlText = strCollapse.GetString();
    sConfig.pszFooterIcon = TD_INFORMATION_ICON;
    sConfig.pszVerificationText = _T("Stop displaying this message");
    sConfig.cxWidth = CMeetingScheduleAssistantApp::DetectMessageBoxWidth();
    
    int iButtonPressed = IDNO; // Default
    BOOL bStopDisplayingMessage = FALSE;
    
    HRESULT hResult = TaskDialogIndirect(&sConfig, &iButtonPressed, NULL, &bStopDisplayingMessage);
    if (hResult == S_OK)
    {
        if (bStopDisplayingMessage)
        {
            CChristianLifeMinistryUtils::HidePromptToSubmitWorkbookDownloadStats();
        }
    }
    
    return iButtonPressed;
    

    enter image description here