2

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

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();
}

我有两个问题,很高兴分成两个问题:

  1. 使用IDI_QUESTION导致应用程序崩溃。
  2. 难道没有更简单的方法来解码nType所需的各种按钮和图标吗?
4

2 回答 2

3

我想我会添加这个作为附加答案。

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

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());
}

我不知道这些:

  • MB_ICONMASK
  • MB_TYPEMASK

我没有满足的唯一情况是MB_ABORTRETRYIGNORE因为我没有看到AbortIgnore的常用按钮等效项。

于 2021-02-02T18:23:15.710 回答
3

使用IDI_QUESTION导致应用程序崩溃

这是因为IDI_QUESTION它是一个标准图标,必须通过将NULL实例句柄传递给 来加载::LoadIcon,但 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
}
于 2021-02-02T18:15:04.070 回答