使用DoMessageBox将AfxMessageBox转换为CTaskDialog



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

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成各种按钮和图标所需的?

使用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
}

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

接受接受的答案(@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,因为我没有看到Abort的通用按钮等效。和.

最新更新