Visual c++ 使用DoMessageBox将AfxMessageBox转换为CTaskDialog

Visual c++ 使用DoMessageBox将AfxMessageBox转换为CTaskDialog,visual-c++,mfc,messagebox,taskdialog,Visual C++,Mfc,Messagebox,Taskdialog,到目前为止,我已经编写了此函数: int CMFCApplication3App::DoMessageBox(LPCTSTR lpszPrompt, UINT nType, UINT nIDPrompt) { CString strContent = CString(lpszPrompt); CString strTitle; strTitle.LoadString(AFX_IDS_APP_TITLE); CTaskDialog dlgTaskMessageBox(str

到目前为止,我已经编写了此函数:

int CMFCApplication3App::DoMessageBox(LPCTSTR lpszPrompt, UINT nType, UINT nIDPrompt)
{
    CString strContent = CString(lpszPrompt);
    CString strTitle; strTitle.LoadString(AFX_IDS_APP_TITLE);
    CTaskDialog dlgTaskMessageBox(strContent, _T(""), strTitle);
    int iPixelWidth = (::GetSystemMetrics(SM_CXSCREEN) / 100) * 30;
    int iDialogUnitsWidth = MulDiv(iPixelWidth, 4, LOWORD(GetDialogBaseUnits()));
    dlgTaskMessageBox.SetDialogWidth(iDialogUnitsWidth);

    /*
    if (nType & MB_ICONINFORMATION)
        dlgTaskMessageBox.SetMainIcon(TD_INFORMATION_ICON);
    if (nType & MB_ICONERROR)
        dlgTaskMessageBox.SetMainIcon(TD_ERROR_ICON);
    if (nType & MB_ICONWARNING)
        dlgTaskMessageBox.SetMainIcon(TD_WARNING_ICON);
    if (nType & MB_ICONQUESTION)
    {
        HICON hIcon = LoadIcon(IDI_QUESTION);
        dlgTaskMessageBox.SetMainIcon(hIcon);
    }

    int iButtons = 0;
    if (nType & IDYES)
        iButtons |= TDCBF_YES_BUTTON;
    if (nType & IDNO)
        iButtons |= TDCBF_NO_BUTTON;
    if (nType & IDCANCEL)
        iButtons |= TDCBF_CANCEL_BUTTON;
    if (nType & IDOK)
        iButtons |= TDCBF_OK_BUTTON;
    if (nType & IDRETRY)
        iButtons |= TDCBF_RETRY_BUTTON;
    dlgTaskMessageBox.SetCommonButtons(iButtons);
    */

    if (nType == (MB_YESNOCANCEL | MB_ICONERROR))
    {
        dlgTaskMessageBox.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
        dlgTaskMessageBox.SetMainIcon(TD_ERROR_ICON);
    }
    if (nType == (MB_YESNOCANCEL | MB_ICONWARNING))
    {
        dlgTaskMessageBox.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
        dlgTaskMessageBox.SetMainIcon(TD_WARNING_ICON);
    }
    if (nType == (MB_YESNOCANCEL | MB_ICONINFORMATION))
    {
        dlgTaskMessageBox.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
        dlgTaskMessageBox.SetMainIcon(TD_INFORMATION_ICON);
    }
    /*
    if (nType == (MB_YESNOCANCEL | MB_ICONQUESTION))
    {
        dlgTaskMessageBox.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
        HICON hIcon = LoadIcon(IDI_QUESTION);
        dlgTaskMessageBox.SetMainIcon(hIcon);
    }
    */
    return dlgTaskMessageBox.DoModal();
}
我对此有两个问题,很高兴分成两个问题:

  • 使用
    IDI_QUESTION
    会导致应用程序崩溃
  • 难道没有更简单的方法将
    nType
    解码为所需的各种按钮和图标吗
  • 使用
    IDI_QUESTION
    会导致应用程序崩溃

    这是因为
    IDI_QUESTION
    是一个问题,必须通过向传递
    NULL
    实例句柄来加载,但MFC的
    CWinApp::LoadIcon
    会传递
    AfxGetResourceHandle()
    。下面的代码绕过MFC,直接调用Win32 API

    HICON hIcon = ::LoadIcon(NULL, IDI_QUESTION);
    
    难道没有一种更简单的方法将nType解码成所需的各种按钮和图标吗

    这并不容易,但可以将它们分组以减少重复

    int nCommonButtons = 0;
    
    switch(nType)
    {
    case MB_YESNOCANCEL:
        nCommonButtons |= TDCBF_CANCEL_BUTTON;
    case MB_YESNO:
        nCommonButtons |= TDCBF_YES_BUTTON | TDCBF_NO_BUTTON; 
        break;
    
    case MB_OKCANCELRETRY:
        nCommonButtons |= TDCBF_RETRY_BUTTON;
    case MB_OKCANCEL:
        nCommonButtons |= TDCBF_CANCEL_BUTTON;
    case MB_OK:
        nCommonButtons |= TDCBF_OK_BUTTON; 
        break;
    
    //... etc
    }
    

    我想我会加上这个作为补充答案

    接受接受的答案(@dxiv)和下面的评论(@sergiol):

    int-CMeetingScheduleAssistantApp::DoMessageBox(LPCTSTR-lpszPrompt、UINT-nType、UINT-nIDPrompt)
    {
    CString strContent=CString(lpszPrompt);
    CString strTitle=CString();
    如果(!CTaskDialog::IsSupported())
    返回CWinAppEx::DoMessageBox(lpszPrompt、nType、nIDPrompt);
    确保(strTitle.LoadString(AFX_id_APP_TITLE));
    CTaskDialog dlgTaskMessageBox(strContent,T(“”),strTitle);
    int iPixelWidth=(::GetSystemMetrics(SM_CXSCREEN)/100)*30;
    intIDialogunitsWidth=MulDiv(iPixelWidth,4,LOWORD(GetDialogBaseUnits());
    dlgTaskMessageBox.SetDialogWidth(iDialogUnitsWidth);
    HICON hQuestionIcon=::加载图标(nullptr,IDI_问题);
    //图标
    交换机(nType&MB_ICONMASK)
    {
    案例MB_i错误:
    dlgTaskMessageBox.SetMainIcon(TD_错误_图标);
    打破
    案例MB_i警告:
    dlgTaskMessageBox.setmain图标(TD_警告_图标);
    打破
    案例MB_信息:
    dlgTaskMessageBox.SetMainIcon(TD_信息_图标);
    打破
    案例MB_i质询:
    dlgTaskMessageBox.SetMainIcon(hQuestionIcon);
    打破
    }
    //钮扣
    int=0;
    开关(nType和MB_类型掩码)
    {
    案例MB_是否取消:
    nCommonButtons |=TDCBF_CANCEL_按钮;
    [[fallthrough]];
    案例MB_YESNO:
    nCommonButtons |=TDCBF|U YES|U按钮| TDCBF|U NO|按钮;
    打破
    案例MB_RETRYCANCEL:
    nCommonButtons |=TDCBF |重试|按钮| TDCBF |否|按钮;
    打破
    案例MB_Oku取消:
    nCommonButtons |=TDCBF_CANCEL_按钮;
    [[fallthrough]];
    案例MB_OK:
    违约:
    nCommonButtons |=TDCBF_OK_按钮;
    }
    dlgTaskMessageBox.SetCommonButtons(nCommonButtons);
    返回static_cast(dlgTaskMessageBox.DoModal());
    }
    
    我不知道这些:

    • MB_ICONMASK
    • MB_类型掩码


    我唯一没有考虑的场景是
    MB_ABORTRETRYIGNORE
    ,因为我没有看到类似于AbortIgnore的常见按钮,谢谢。我现在可以用了。我也加了我自己的答案。很高兴它有帮助。你的也行。问题是,我不知道在两组标志之间映射的内置方式,因此必须以这种或那种方式手动完成。@andrewruckle这应该是
    IDI_hand
    (与
    IDI_ERROR
    相同)。这两个函数在这里没有多大帮助,因为它们在CTaskDialog样式和标准按钮ID之间映射,而标准按钮ID与MessageBox样式不直接对应。@AndrewTruckle是的,这两个是.Doh-我不需要更新代码,然后保存值。已经抓到了。为什么你把按钮可见性的逻辑和图标的逻辑混为一谈?对于图标,您可以执行类似于
    switch(nType&MB\u ICONMASK)
    的操作;对于按钮
    switch(nType&MB\u TYPEMASK)
    @sergiol,MB\u ICONMASK等具体是什么?这些是检索按钮和图标值的专用工具吗?MFC的文档记录在哪里?这些文档记录得很差或不清楚。我记得我们以前在这里做过的一些事情的标志,但它们本质上是一个屏蔽,根据用途过滤一些
    MB.*
    值。有时,了解MFC的更好方法是查看所提供的基本源代码,或者在其中放置一些断点。@IInspectable您知道关于
    MB_*MASK
    实体的任何文档吗?
    int CMeetingScheduleAssistantApp::DoMessageBox(LPCTSTR lpszPrompt, UINT nType, UINT nIDPrompt)
    {
        CString strContent = CString(lpszPrompt);
        CString strTitle = CString();
    
        if (!CTaskDialog::IsSupported())
            return CWinAppEx::DoMessageBox(lpszPrompt, nType, nIDPrompt);
    
        ENSURE(strTitle.LoadString(AFX_IDS_APP_TITLE));
        CTaskDialog dlgTaskMessageBox(strContent, _T(""), strTitle);
    
        int iPixelWidth = (::GetSystemMetrics(SM_CXSCREEN) / 100) * 30;
        int iDialogUnitsWidth = MulDiv(iPixelWidth, 4, LOWORD(GetDialogBaseUnits()));
        dlgTaskMessageBox.SetDialogWidth(iDialogUnitsWidth);
        HICON hQuestionIcon = ::LoadIcon(nullptr, IDI_QUESTION);
    
        // Icon
        switch (nType & MB_ICONMASK)
        {
        case MB_ICONERROR:
            dlgTaskMessageBox.SetMainIcon(TD_ERROR_ICON);
            break;
        case MB_ICONWARNING:
            dlgTaskMessageBox.SetMainIcon(TD_WARNING_ICON);
            break;
        case MB_ICONINFORMATION:
            dlgTaskMessageBox.SetMainIcon(TD_INFORMATION_ICON);
            break;
        case MB_ICONQUESTION:
            dlgTaskMessageBox.SetMainIcon(hQuestionIcon);
            break;
        }
    
        // Buttons
        int nCommonButtons = 0;
        switch (nType & MB_TYPEMASK)
        {
        case MB_YESNOCANCEL:
            nCommonButtons |= TDCBF_CANCEL_BUTTON;
            [[fallthrough]];
        case MB_YESNO:
            nCommonButtons |= TDCBF_YES_BUTTON | TDCBF_NO_BUTTON;
            break;
    
        case MB_RETRYCANCEL:
            nCommonButtons |= TDCBF_RETRY_BUTTON | TDCBF_NO_BUTTON;
            break;
    
        case MB_OKCANCEL:
            nCommonButtons |= TDCBF_CANCEL_BUTTON;
            [[fallthrough]];
        case MB_OK:
        default:
            nCommonButtons |= TDCBF_OK_BUTTON;
        }
        dlgTaskMessageBox.SetCommonButtons(nCommonButtons);
    
        return static_cast<int>(dlgTaskMessageBox.DoModal());
    }