📄 xmessagebox.cpp
字号:
::WritePrivateProfileString(_T("DoNotAsk"), // section name
szKey, // key name
szData, // string to add
szPathName); // initialization file
#endif // XMESSAGEBOX_USE_PROFILE_FILE
#ifdef _DEBUG
// verify that we can read data
DWORD dwData = 0;
#ifndef XMESSAGEBOX_USE_PROFILE_FILE
// read from registry
dwData = ReadRegistry(Me->m_szCompanyName, szKey);
TRACE(_T("dwData=0x%08X\n"), dwData);
#else
// read from ini file
TCHAR szBuf[100];
::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
_ASSERTE(dwData == (DWORD) wParam);
#endif // _DEBUG
}
#endif // #ifndef XMESSAGEBOX_DO_NOT_SAVE_CHECKBOX
::EndDialog(hwnd, wParam);
return FALSE;
}
}
case WM_LBUTTONDOWN:
case WM_NCLBUTTONDOWN:
{
// user clicked on dialog or titlebar - stop the timer
::KillTimer(hwnd, 1);
if (Me->GetDefaultButtonId())
{
HWND hwndDefButton = ::GetDlgItem(hwnd, Me->GetDefaultButtonId());
if (hwndDefButton && ::IsWindow(hwndDefButton))
{
if (Me->m_szDefaultButton[0] != _T('\0'))
{
::SetWindowText(hwndDefButton, Me->m_szDefaultButton);
}
}
}
return FALSE;
}
case WM_TIMER: // used for timeout
{
TRACE(_T("in WM_TIMER\n"));
if (wParam == 1) // timeout timer
{
if (Me->m_nTimeoutSeconds <= 0)
{
::KillTimer(hwnd, wParam);
// time's up, select default button
::SendMessage(hwnd, WM_COMMAND, Me->GetDefaultButtonId() | MB_TIMEOUT, 0);
return FALSE;
}
if (Me->GetDefaultButtonId() == 0)
return FALSE;
HWND hwndDefButton = ::GetDlgItem(hwnd, Me->GetDefaultButtonId());
if (hwndDefButton == NULL || !::IsWindow(hwndDefButton))
return FALSE;
if (Me->m_szDefaultButton[0] == _T('\0'))
{
// first time - get text of default button
::GetWindowText(hwndDefButton, Me->m_szDefaultButton,
MaxButtonStringSize);
}
TCHAR szButtonText[MaxButtonStringSize*2];
_stprintf(szButtonText, XMESSAGEBOX_TIMEOUT_TEXT_FORMAT,
Me->m_szDefaultButton, Me->m_nTimeoutSeconds);
::SetWindowText(hwndDefButton, szButtonText);
Me->m_nTimeoutSeconds--;
}
else if (wParam == 2) // disabled timer
{
::KillTimer(hwnd, wParam);
for (UINT nID = 1; nID <= ID_XMESSAGEBOX_LAST_ID; nID++)
{
hwndChild = ::GetDlgItem(hwnd, nID);
if (hwndChild && ::IsWindow(hwndChild))
{
// enable all buttons
TCHAR szClassName[MAX_PATH];
::GetClassName(hwndChild, szClassName, countof(szClassName)-2);
if (_tcsicmp(szClassName, _T("Button")) == 0)
{
LONG nStyle = ::GetWindowLong(hwndChild, GWL_STYLE);
nStyle &= ~WS_DISABLED;
::SetWindowLong(hwndChild, GWL_STYLE, nStyle);
}
}
} // for
if (Me->Option(CancelOrOkButton))
::EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE, MF_ENABLED);
::RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE|RDW_UPDATENOW);
}
}
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////
// CXDialogTemplate::AddItem
void CXDialogTemplate::AddItem(CXDialogItem::Econtroltype cType,
UINT nID,
CXRect* prect,
LPCTSTR pszCaption)
{
_ASSERTE(m_pDlgItemArray[m_dlgTempl.cdit] == NULL);
CXDialogItem::Econtroltype ct = cType;
if (ct == CXDialogItem::CHECKBOX)
ct = CXDialogItem::BUTTON;
m_pDlgItemArray[m_dlgTempl.cdit] = new CXDialogItem(ct);
_ASSERTE(m_pDlgItemArray[m_dlgTempl.cdit]);
m_pDlgItemArray[m_dlgTempl.cdit]->AddItem(*this, cType, nID, prect, pszCaption);
m_dlgTempl.cdit++;
_ASSERTE(m_dlgTempl.cdit < MaxItems);
}
///////////////////////////////////////////////////////////////////////////////
// CXDialogTemplate::Display
int CXDialogTemplate::Display()
{
// The first step is to allocate memory to define the dialog. The information to be
// stored in the allocated buffer is the following:
//
// 1. DLGTEMPLATE structure
// typedef struct
// {
// DWORD style;
// DWORD dwExtendedStyle;
// WORD cdit;
// short x;
// short y;
// short cx;
// short cy;
// } DLGTEMPLATE;
// 2. 0x0000 (Word) indicating the dialog has no menu
// 3. 0x0000 (Word) Let windows assign default class to the dialog
// 4. (Caption) Null terminated unicode string
// 5. 0x000B (size of the font to be used)
// 6. "MS Sans Serif" (name of the typeface to be used)
// 7. DLGITEMTEMPLATE structure for the button (HAS TO BE DWORD ALIGNED)
// typedef struct
// {
// DWORD style;
// DWORD dwExtendedStyle;
// short x;
// short y;
// short cx;
// short cy;
// WORD id;
// } DLGITEMTEMPLATE;
// 8. 0x0080 to indicate the control is a button
// 9. (Title). Unicode null terminated string with the caption
// 10. 0x0000 0 extra bytes of data for this control
// 11. DLGITEMTEMPLATE structure for the Static Text (HAS TO BE DWORD ALIGNED)
// 12. 0x0081 to indicate the control is static text
// 13. (Title). Unicode null terminated string with the text
// 14. 0x0000. 0 extra bytes of data for this control
int rc = IDCANCEL;
TCHAR szTitle[1024];
_tcsncpy(szTitle, m_lpszCaption, countof(szTitle)-1);
szTitle[countof(szTitle)-1] = _T('\0');
size_t nTitleLen = _tcslen(szTitle);
int i = 0;
size_t nBufferSize = sizeof(DLGTEMPLATE) +
(2 * sizeof(WORD)) + // menu and class
((nTitleLen + 1) * sizeof(WCHAR));
// NOTE - font is set in MsgBoxDlgProc
nBufferSize = (nBufferSize + 3) & ~3; // adjust size to make
// first control DWORD aligned
// loop to calculate size of buffer we need -
// add size of each control:
// sizeof(DLGITEMTEMPLATE) +
// sizeof(WORD) + // atom value flag 0xFFFF
// sizeof(WORD) + // ordinal value of control's class
// sizeof(WORD) + // no. of bytes in creation data array
// sizeof title in WCHARs
for (i = 0; i < m_dlgTempl.cdit; i++)
{
size_t nItemLength = sizeof(DLGITEMTEMPLATE) + 3 * sizeof(WORD);
#ifdef _UNICODE
size_t nActualChars = _tcslen(m_pDlgItemArray[i]->m_pszCaption) + 1; //+++1.5;
#else
int nActualChars = MultiByteToWideChar(CP_ACP, 0,
(LPCSTR)m_pDlgItemArray[i]->m_pszCaption,
-1, NULL, 0); //+++1.5
#endif
ASSERT(nActualChars > 0);
nItemLength += nActualChars * sizeof(WCHAR);
if (i != m_dlgTempl.cdit - 1) // the last control does not need extra bytes
{
nItemLength = (nItemLength + 3) & ~3; // take into account gap
} // so next control is DWORD aligned
nBufferSize += nItemLength;
}
HLOCAL hLocal = LocalAlloc(LHND, nBufferSize);
_ASSERTE(hLocal);
if (hLocal == NULL)
return IDCANCEL;
BYTE* pBuffer = (BYTE*)LocalLock(hLocal);
_ASSERTE(pBuffer);
if (pBuffer == NULL)
{
LocalFree(hLocal);
return IDCANCEL;
}
BYTE* pdest = pBuffer;
// transfer DLGTEMPLATE structure to the buffer
memcpy(pdest, &m_dlgTempl, sizeof(DLGTEMPLATE));
pdest += sizeof(DLGTEMPLATE);
*(WORD*)pdest = 0; // no menu
pdest += sizeof(WORD); //+++1.5
*(WORD*)pdest = 0; // use default window class //+++1.5
pdest += sizeof(WORD); //+++1.5
// transfer title
WCHAR * pchCaption = new WCHAR[nTitleLen + 100];
memset(pchCaption, 0, nTitleLen*2 + 2);
#ifdef _UNICODE
memcpy(pchCaption, szTitle, nTitleLen * sizeof(TCHAR));
size_t nActualChars = nTitleLen + 1;
#else
size_t nActualChars = MultiByteToWideChar(CP_ACP, 0,
(LPCSTR)szTitle, -1, pchCaption, nTitleLen + 1);
#endif
_ASSERTE(nActualChars > 0);
memcpy(pdest, pchCaption, nActualChars * sizeof(WCHAR));
pdest += nActualChars * sizeof(WCHAR);
delete [] pchCaption; //+++1.5
// will now transfer the information for each one of the item templates
for (i = 0; i < m_dlgTempl.cdit; i++)
{
pdest = (BYTE*)(((UINT_PTR)pdest + 3) & ~3); // make the pointer DWORD aligned
memcpy(pdest, (void *)&m_pDlgItemArray[i]->m_dlgItemTemplate,
sizeof(DLGITEMTEMPLATE));
pdest += sizeof(DLGITEMTEMPLATE);
*(WORD*)pdest = 0xFFFF; // indicating atom value
pdest += sizeof(WORD);
*(WORD*)pdest = (WORD)m_pDlgItemArray[i]->m_controltype; // atom value for the control
pdest += sizeof(WORD);
// transfer the caption even when it is an empty string
size_t nChars = _tcslen(m_pDlgItemArray[i]->m_pszCaption) + 1; //+++1.5
WCHAR * pchCaption = new WCHAR[nChars+100];
#ifdef _UNICODE
memset(pchCaption, 0, nChars*sizeof(TCHAR) + 2);
memcpy(pchCaption, m_pDlgItemArray[i]->m_pszCaption, nChars * sizeof(TCHAR)); //+++1.5
size_t nActualChars = nChars;
#else
size_t nActualChars = MultiByteToWideChar(CP_ACP, 0,
(LPCSTR)m_pDlgItemArray[i]->m_pszCaption, -1, pchCaption, nChars); //+++1.5
#endif
_ASSERTE(nActualChars > 0);
memcpy(pdest, pchCaption, nActualChars * sizeof(WCHAR));
pdest += nActualChars * sizeof(WCHAR);
delete [] pchCaption; //+++1.5
*(WORD*)pdest = 0; // How many bytes in data for control
pdest += sizeof(WORD);
}
_ASSERTE((size_t)(pdest - pBuffer) <= nBufferSize); //+++1.5 // just make sure we did not overrun the heap
HINSTANCE hInstance = GetModuleHandle(NULL);
rc = ::DialogBoxIndirectParam(hInstance, (LPCDLGTEMPLATE) pBuffer, m_hWnd,
MsgBoxDlgProc, (LPARAM)this);
LocalUnlock(hLocal);
LocalFree(hLocal);
return rc;
}
///////////////////////////////////////////////////////////////////////////////
// CXDialogItem class
///////////////////////////////////////////////////////////////////////////////
// CXDialogItem ctor
CXDialogItem::CXDialogItem(CXDialogItem::Econtroltype ctrlType) :
m_controltype(ctrlType),
m_pszCaption(NULL) //+++1.5
{
}
///////////////////////////////////////////////////////////////////////////////
// CXDialogItem dtor
CXDialogItem::~CXDialogItem()
{
if (m_pszCaption)
delete [] m_pszCaption;
}
///////////////////////////////////////////////////////////////////////////////
// CXDialogItem::AddItem
void CXDialogItem::AddItem(CXDialogTemplate& dialog,
Econtroltype ctrltype,
UINT nID,
CXRect* prect,
LPCTSTR lpszCaption)
{
short hidbu = HIWORD(GetDialogBaseUnits());
short lodbu = LOWORD(GetDialogBaseUnits());
// first fill in the type, location and size of the control
m_controltype = ctrltype;
if (m_controltype == CHECKBOX)
m_controltype = BUTTON;
if (prect != NULL)
{
m_dlgItemTemplate.x = (short)((prect->left * 4) / lodbu);
m_dlgItemTemplate.y = (short)((prect->top * 8) / hidbu);
m_dlgItemTemplate.cx = (short)((prect->Width() * 4) / lodbu);
m_dlgItemTemplate.cy = (short)((prect->Height() * 8) / hidbu);
}
else
{
m_dlgItemTemplate.x = 0;
m_dlgItemTemplate.y = 0;
m_dlgItemTemplate.cx = 10; // some useless default
m_dlgItemTemplate.cy = 10;
}
m_dlgItemTemplate.dwExtendedStyle = 0;
m_dlgItemTemplate.id = (WORD)nID;
switch (ctrltype)
{
case ICON:
m_dlgItemTemplate.style = WS_CHILD | SS_ICON | WS_VISIBLE;
break;
case BUTTON:
dialog.GetButtonCount()++;
m_dlgItemTemplate.style = WS_VISIBLE | WS_CHILD | WS_TABSTOP;
if (dialog.GetButtonCount() == dialog.GetDefaultButton())
{
m_dlgItemTemplate.style |= BS_DEFPUSHBUTTON;
dialog.SetDefaultButtonId(nID);
}
else
{
m_dlgItemTemplate.style |= BS_PUSHBUTTON;
}
break;
case CHECKBOX:
m_dlgItemTemplate.style = WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_AUTOCHECKBOX;
break
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -