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
,因为我没有看到类似于Abort和Ignore的常见按钮,谢谢。我现在可以用了。我也加了我自己的答案。很高兴它有帮助。你的也行。问题是,我不知道在两组标志之间映射的内置方式,因此必须以这种或那种方式手动完成。@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());
}