📄 xmessagebox.cpp
字号:
// lpszMessage - Pointer to a null-terminated string containing the
// message to be displayed.
//
// lpszCaption - Pointer to a null-terminated string used for the
// dialog box title. If this parameter is NULL, the
// default title Error is used.
//
// nStyle - Specifies a set of bit flags that determine the
// contents and behavior of the dialog box. This
// parameter can be a combination of flags from the
// following groups of flags.
//
// pXMB - Pointer to optional parameters. The parameters
// struct XMSGBOXPARAMS is defined in XMessageBox.h.
//
///////////////////////////////////////////////////////////////////////////////
int XMessageBox(HWND hwnd,
LPCTSTR lpszMessage,
LPCTSTR lpszCaption /*= NULL*/,
UINT nStyle /*= MB_OK | MB_ICONEXCLAMATION*/,
XMSGBOXPARAMS * pXMB /*= NULL*/)
{
_ASSERTE(lpszMessage);
if (hwnd == NULL)
{
hwnd = ::GetActiveWindow() ;
if (hwnd != NULL)
{
hwnd = ::GetLastActivePopup(hwnd) ;
}
};
if ((nStyle & MB_ICONHAND) && (nStyle & MB_SYSTEMMODAL))
{
// NOTE: When an application calls MessageBox and specifies the
// MB_ICONHAND and MB_SYSTEMMODAL flags for the nStyle parameter,
// the system displays the resulting message box regardless of
// available memory.
return ::MessageBox(hwnd, lpszMessage, lpszCaption, nStyle);
}
if (lpszCaption == NULL || lpszCaption[0] == 0)
lpszCaption = _T("Error");
XMSGBOXPARAMS xmb;
if (pXMB)
xmb = *pXMB;
#ifndef XMESSAGEBOX_DO_NOT_SAVE_CHECKBOX
// are Do Not Ask styles specified?
if ((nStyle & MB_DONOTASKAGAIN) ||
(nStyle & MB_DONOTTELLAGAIN) ||
(nStyle & MB_DONOTSHOWAGAIN))
{
// is module name supplied?
if (xmb.lpszModule && (xmb.lpszModule[0] != _T('\0')))
{
// caller specified Do No Ask style and a module name -
// check if answer previously saved in ini file
// get full path to ini file
TCHAR szPathName[MAX_PATH*2];
szPathName[0] = _T('\0');
::GetModuleFileName(NULL, szPathName, countof(szPathName)-1);
TCHAR *cp = _tcsrchr(szPathName, _T('\\'));
if (cp != NULL)
*(cp+1) = _T('\0');
_tcscat(szPathName, XMESSAGEBOX_INI_FILE);
// key is module name and line
TCHAR szKey[MAX_PATH*2];
_tcscpy(szKey, xmb.lpszModule);
TRACE(_T("szKey=<%s>\n"), szKey);
encode(szKey); // simple encoding to obscure module name
TCHAR szLine[100];
szLine[0] = _T('\0');
_tcscat(szKey, _itot(xmb.nLine, szLine, 10));
TRACE(_T("szKey=<%s>\n"), szKey);
TCHAR szBuf[100];
szBuf[0] = _T('\0');
DWORD dwData = 0;
#ifndef XMESSAGEBOX_USE_PROFILE_FILE
// read from registry
dwData = ReadRegistry(xmb.szCompanyName, szKey);
TRACE(_T("dwData=0x%08X\n"), dwData);
#else
// read from ini file
// data string is hex value of XMessageBox return code
::GetPrivateProfileString(_T("DoNotAsk"), // section name
szKey, // key name
_T(""), // default string
szBuf, // destination buffer
countof(szBuf)-1, // size of destination buffer
szPathName); // initialization file name
dwData = _tcstoul(szBuf, NULL, 16);
TRACE(_T("szBuf=<%s> dwData=0x%08X\n"), szBuf, dwData);
#endif // XMESSAGEBOX_USE_PROFILE_FILE
// Note: dwData will be 0 if either ReadRegistry or
// GetPrivateProfileString fail to find key
if ((dwData & MB_DONOTASKAGAIN) ||
(dwData & MB_DONOTTELLAGAIN) ||
(dwData & MB_DONOTSHOWAGAIN))
{
TRACE(_T("saved DoNotAsk found, returning 0x%08X\n"), dwData);
return (int)dwData;
}
}
}
#endif // #ifndef XMESSAGEBOX_DO_NOT_SAVE_CHECKBOX
// should be seconds, not milliseconds
_ASSERTE(xmb.nTimeoutSeconds < 1000);
if (xmb.nTimeoutSeconds >= 1000)
xmb.nTimeoutSeconds = 10;
// should be seconds, not milliseconds
_ASSERTE(xmb.nDisabledSeconds < 1000);
if (xmb.nDisabledSeconds >= 1000)
xmb.nDisabledSeconds = 10;
// cannot have both disabled and timeout seconds
_ASSERTE(xmb.nDisabledSeconds == 0 || xmb.nTimeoutSeconds == 0);
CXDialogTemplate dlg(hwnd,
lpszMessage,
lpszCaption,
nStyle,
&xmb);
if ((nStyle & MB_NOSOUND) == 0)
::MessageBeep(nStyle & MB_ICONMASK);
int rc = dlg.Display();
return rc;
}
///////////////////////////////////////////////////////////////////////////////
// IconProc
LONG CALLBACK IconProc(HWND hwnd, UINT message, WPARAM, LPARAM)
{
if (message == WM_PAINT)
{
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hwnd, &ps);
::DrawIcon(hdc, 0, 0, (HICON)(UINT_PTR)(::GetWindowLong(hwnd, GWL_USERDATA)));
EndPaint(hwnd, &ps);
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////
// CXDialogTemplate class
///////////////////////////////////////////////////////////////////////////////
// CXDialogTemplate ctor
CXDialogTemplate::CXDialogTemplate(HWND hWnd,
LPCTSTR lpszMessage,
LPCTSTR lpszCaption,
UINT nStyle,
XMSGBOXPARAMS *pXMB) :
m_hWnd(hWnd),
m_lpszMessage(NULL),
m_lpszCaption(NULL),
m_nStyle(nStyle),
m_nHelpId(pXMB->nIdHelp),
m_hInstanceStrings(pXMB->hInstanceStrings),
m_hInstanceIcon(pXMB->hInstanceIcon),
m_lpReportFunc(pXMB->lpReportFunc),
m_dwReportUserData(pXMB->dwReportUserData),
m_nTimeoutSeconds(pXMB->nTimeoutSeconds),
m_nDisabledSeconds(pXMB->nDisabledSeconds),
m_Options(EDefault),
m_hIcon(NULL),
m_hFont(NULL),
m_nButton(0), // current button no.
m_nDefId(1), // button number of default button
m_nMaxID(FirstControlId), // control id
m_X(pXMB->x),
m_Y(pXMB->y),
m_lpszModule(pXMB->lpszModule),
m_nLine(pXMB->nLine),
m_bRightJustifyButtons(pXMB->dwOptions & XMSGBOXPARAMS::RightJustifyButtons)
{
// store company name to use for saving checkbox state in registry
memset(m_szCompanyName, 0, sizeof(m_szCompanyName));
_tcscpy(m_szCompanyName, pXMB->szCompanyName);
// m_szDefaultButton is used to save text for timeout option
memset(m_szDefaultButton, 0, sizeof(m_szDefaultButton));
///////////////////////////////////////////////////////////////////////////
// allocate buffers for message and caption - buffers must be allocated
// (instead of just using pointers) because we may need to load the strings
// from resources
m_lpszMessage = new TCHAR [MessageSize];
if (m_lpszMessage)
m_lpszMessage[0] = _T('\0');
memset(m_lpszMessage, 0, MessageSize);
m_lpszCaption = new TCHAR [MessageSize];
if (m_lpszCaption)
m_lpszCaption[0] = _T('\0');
memset(m_lpszCaption, 0, MessageSize);
///////////////////////////////////////////////////////////////////////////
// set instance handle for strings
HINSTANCE hInstanceStrings = m_hInstanceStrings;
if (!hInstanceStrings)
hInstanceStrings = ::GetModuleHandle(NULL);
///////////////////////////////////////////////////////////////////////////
// load message text from resource or string
if (lpszMessage)
{
if (HIWORD(lpszMessage) == NULL)
{
// looks like a resource id
if (::LoadString(hInstanceStrings,
LOWORD((UINT_PTR)lpszMessage),
m_lpszMessage,
MessageSize-1) == 0)
m_lpszMessage[0] = _T('\0');
}
else
{
// looks like a string pointer
_tcsncpy(m_lpszMessage, lpszMessage, MessageSize-1);
}
m_lpszMessage[MessageSize-1] = _T('\0');
}
///////////////////////////////////////////////////////////////////////////
// load caption from resource or string
if (lpszCaption)
{
if (HIWORD(lpszCaption) == NULL)
{
// looks like a resource id
if (::LoadString(hInstanceStrings,
LOWORD((UINT_PTR)lpszCaption),
m_lpszCaption,
MessageSize-1) == 0)
m_lpszCaption[0] = _T('\0');
}
else
{
// looks like a string pointer
_tcsncpy(m_lpszCaption, lpszCaption, MessageSize-1);
}
m_lpszCaption[MessageSize-1] = _T('\0');
}
///////////////////////////////////////////////////////////////////////////
// load custom buttons from resource or string
memset(m_szCustomButtons, 0, sizeof(m_szCustomButtons));
if (pXMB->nIdCustomButtons)
{
// load from resource id
if (::LoadString(hInstanceStrings,
pXMB->nIdCustomButtons,
m_szCustomButtons,
countof(m_szCustomButtons)-1) == 0)
m_szCustomButtons[0] = _T('\0');
}
if ((m_szCustomButtons[0] == _T('\0')) && (pXMB->szCustomButtons[0] != _T('\0')))
{
// load from string
_tcsncpy(m_szCustomButtons, pXMB->szCustomButtons, countof(m_szCustomButtons)-1);
}
m_szCustomButtons[countof(m_szCustomButtons)-1] = _T('\0');
///////////////////////////////////////////////////////////////////////////
// load report button caption from resource or string
memset(szReport, 0, sizeof(szReport));
if (pXMB->nIdReportButtonCaption)
{
// load from resource id
if (::LoadString(hInstanceStrings,
pXMB->nIdReportButtonCaption,
szReport,
MaxButtonStringSize-1) == 0)
szReport[0] = _T('\0');
}
if ((szReport[0] == _T('\0')) && (pXMB->szReportButtonCaption[0] != _T('\0')))
{
_tcsncpy(szReport, pXMB->szReportButtonCaption, MaxButtonStringSize-1);
}
szReport[MaxButtonStringSize-1] = _T('\0');
///////////////////////////////////////////////////////////////////////////
// load button captions from resource or use default strings
//-[UK
if ( pXMB->bUseUserDefinedButtonCaptions )
{
LoadUserDefinedButtonStrings( pXMB->UserDefinedButtonCaptions );
}
else
{
//-]UK
if (nStyle & MB_NORESOURCE)
LoadButtonStrings(); // use English strings
else
LoadButtonStringsFromResources(hInstanceStrings); // try to load from resource strings
//-[UK
}
//-]UK
///////////////////////////////////////////////////////////////////////////
// get dc for drawing
HDC hdc = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
_ASSERTE(hdc);
///////////////////////////////////////////////////////////////////////////
// get message font
NONCLIENTMETRICS ncm;
memset(&ncm, 0, sizeof(ncm));
ncm.cbSize = sizeof(ncm);
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
m_hFont = ::CreateFontIndirect(&ncm.lfMessageFont);
HFONT hOldFont = (HFONT)::SelectObject(hdc, m_hFont);
int nMaxWidth = (::GetSystemMetrics(SM_CXSCREEN) / 2) + 80; //+++1.5
if (nStyle & MB_ICONMASK)
nMaxWidth -= GetSystemMetrics(SM_CXICON) + 2*SpacingSize;
CXRect msgrect;
SetRect(&msgrect, 0, 0, nMaxWidth, nMaxWidth);
///////////////////////////////////////////////////////////////////////////
// get output size of message text
::DrawText(hdc, GetMessageText(), -1, &msgrect, DT_LEFT | DT_NOPREFIX |
DT_WORDBREAK | DT_CALCRECT | DT_EXPANDTABS); //+++1.5
msgrect.right += 12;
msgrect.bottom += 5;
msgrect.left = 2 * SpacingSize;
msgrect.top = 2 * SpacingSize;
msgrect.right += 2 * SpacingSize;
msgrect.bottom += 2 * SpacingSize;
// client rect
CXRect mbrect;
SetRect(&mbrect, 0, 0,
msgrect.Width() + (2 * SpacingSize),
msgrect.Height() + (2 * SpacingSize));
if (mbrect.Height() < MinimalHeight)
mbrect.bottom = MinimalHeight;
///////////////////////////////////////////////////////////////////////////
// initialize the DLGTEMPLATE structure
m_dlgTempl.x = 0;
m_dlgTempl.y = 0;
m_dlgTempl.cdit = 0;
m_dlgTempl.style = WS_CAPTION | WS_VISIBLE | WS_SYSMENU |
WS_POPUP | DS_MODALFRAME | DS_CENTER;
m_dlgTempl.dwExtendedStyle = 0;
if (nStyle & MB_SYSTEMMODAL)
m_dlgTempl.style |= DS_SYSMODAL;
for (int j = 0; j < MaxItems; j++)
m_pDlgItemArray[j] = NULL;
int x, y;
CXRect iconrect;
SetRect(&iconrect, 0, 0, 0, 0);
CXRect rect;
HINSTANCE hInstanceIcon = m_hInstanceIcon;
if (!hInstanceIcon)
hInstanceIcon = ::GetModuleHandle(NULL);
///////////////////////////////////////////////////////////////////////////
// load icon by id or by name
if (pXMB->nIdIcon)
{
m_hIcon = ::LoadIcon(hInstanceIcon, MAKEINTRESOURCE(pXMB->nIdIcon));
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
int icon_x = SpacingSize;
int icon_y = SpacingSize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -