/* ��������� � ����������� ���������
+ 1. ������� �������� checkbox �� ���������
2. ������� ���������� �������, ��������� �������� DonAskAgain (�� ������� ����
��� ��� ����� ���������� ������)
+ 3. �������������� �������� ���������������� ������ � ����������� �� ����� ������ ������
+ 4. �������� ���������� ������ �� �������� ����������
5. �������� ����������� ���������� checkbox, �������������� ���� WinXP
*/
#include "stdafx.h"
#ifdef _MFC_VER
#pragma message(" compiling for MFC")
#define CPPString CString //MFC program
#else
#pragma message(" compiling for Win32")
#include <windows.h>
#include <stdio.h>
#include <crtdbg.h>
#include <tchar.h>
#include "StdString.h"
#ifdef _UNICODE
#define CPPString CStdStringW //non-MFC program UNICODE
#else
#define CPPString CStdStringA //non-MFC program ANSI
#endif
#endif
#include "PPMessageBox.h"
#include "PPHtmlDrawer.h"
//SetWindowLongPtr is available on _WIN64 platform
#ifndef SetWindowLongPtr
#define SetWindowLongPtr SetWindowLong
#endif
#pragma warning(disable : 4127) // conditional expression is constant
//////////////////////////////////////////////////////////////
//
//
#define PPMSGBOX_DO_NOT_SAVE_CHECKBOX
//////////////////////////////////////////////////////////////
//Uncomments a following line if you want store "DoNotAsk" value to INI file
//
//#define PPMSGBOX_USE_PROFILE_FILE
//The sizes
#define PPMSGBOX_SIZE_SEPX 0
#define PPMSGBOX_SIZE_MSGX 1
#define PPMSGBOX_SIZE_MSGY 2
#define PPMSGBOX_SIZE_BTNX 3
#define PPMSGBOX_SIZE_BTNY 4
#define PPMSGBOX_SIZE_CHKX 5
#define PPMSGBOX_SIZE_CHKY 6
#define PPMSGBOX_SIZE_CTRLX 7
#define PPMSGBOX_SIZE_CTRLY 8
#define PPMSGBOX_BUTTON_DISABLED _T("%s = %d")
#define PPMSGBOX_INI_FILE _T("PPMessageBox.ini")
#define PPMSGBOX_REGISTRY_KEY _T("PPMessageBox")
#define UDM_HTMLDRAWER_REPAINT (WM_APP + 100)
class CPPMessageBoxTemplate
{
public:
CPPMessageBoxTemplate(const PPMSGBOXPARAMS *pMsgBox); //Constructor of CPPMessageBoxTemplate
virtual ~CPPMessageBoxTemplate();
int Display();
protected:
#pragma pack(1)
typedef struct _STRUCT_BUTTONS
{
_STRUCT_BUTTONS()
{
hWnd = NULL;
nTypeBtn = 0;
}
int nTypeBtn; //The Type of the Button
HWND hWnd; //HWND of the button
} STRUCT_BUTTONS;
#pragma pack()
typedef std::vector<STRUCT_BUTTONS> vecButton; //Buttons
vecButton m_vecButtons;
STRUCT_BUTTONS m_stCheckBtn;
STRUCT_BUTTONS m_stCheckText;
DWORD m_dwSizes [PPMSGBOX_SIZE_CTRLY + 1]; //The sizes
HICON m_hIcon;
PPMSGBOXPARAMS m_MsgParam;
UINT m_nDefBtn; //A default button index (0 - to max counts of the buttons)
HFONT m_hFont;
DWORD m_dwHeaderHeight;
DWORD m_dwMessageHeight;
DWORD m_dwControlHeight;
DWORD m_dwMoreInfoHeight;
BOOL m_bIsCancelExist;
BOOL m_bMoreInfoOpened;
DWORD m_dwCountdownTimer;
CPPString m_sDisabledCaption;
CPPString m_sHeaderSepText;
CPPString m_sControlSepText;
CPPString m_sMoreInfoSepText;
CPPString m_sText;
CPPString m_sCaption;
CPPString m_sHeader;
CPPString m_sMoreInfoOpened; //Text for the opened "MoreInfo" button
CPPString m_sMoreInfoClosed; //Text for the closed "MoreInfo" button
CPPString m_sTimeoutText; //Text for the timeout button or the timeout caption
CPPHtmlDrawer m_pHeader;
CPPHtmlDrawer m_pDrawer;
CPPHtmlDrawer m_pMoreInfo;
HBITMAP m_hBitmapBk;
SIZE PrepareMessageBox(HWND hwnd);
void RemoveAllButtons();
CPPString GetString(LPCTSTR lpszText);
CPPString GetLocalizedButtonText(DWORD dwBtnID, CPPString sDefText = _T(""));
void OnInitDialog(HWND hwnd);
void OnTimer(HWND hwnd);
//Draw methods
void DrawBox(HWND hwnd, HDC hDC);
void DrawSeparator(HDC hDC, LPCRECT lpRect, int nTypeSeparator, LPCTSTR lpszText, int nTextAlign);
static BOOL CALLBACK MsgBoxDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
};
int PPMessageBox(HWND hwnd,
LPCTSTR lpszMessage,
LPCTSTR lpszCaption /*= NULL*/,
DWORD dwStyle /*= MB_OK | MB_ICONEXCLAMATION*/,
const PPMSGBOXPARAMS * pMsgBox /*= NULL*/)
{
PPMSGBOXPARAMS MsgBox;
if (NULL != pMsgBox)
MsgBox = *pMsgBox;
MsgBox.lpszCaption = lpszCaption;
MsgBox.lpszText = lpszMessage;
MsgBox.dwStyle = dwStyle;
MsgBox.hParentWnd = hwnd;
return PPMessageBoxIndirect(&MsgBox);
} //End of PPMessageBox
int PPMessageBoxIndirect(const PPMSGBOXPARAMS * pMsgBox)
{
_ASSERT(pMsgBox);
_ASSERT((NULL != pMsgBox->lpszText) && (0 != pMsgBox->lpszText [0]));
// cannot have both disabled and timeout seconds
// _ASSERT((pMsgBox->nDisabledSeconds == 0) || (pMsgBox->nTimeoutSeconds == 0));
PPMSGBOXPARAMS MsgBox;
MsgBox = *pMsgBox;
if (MsgBox.hParentWnd == NULL)
{
MsgBox.hParentWnd = ::GetActiveWindow();
if (MsgBox.hParentWnd != NULL)
MsgBox.hParentWnd = ::GetLastActivePopup(MsgBox.hParentWnd);
} //if
TCHAR tchCaption[MAX_PATH];
if ((NULL == MsgBox.lpszCaption) || (0 == MsgBox.lpszCaption [0]))
{
if (NULL != MsgBox.hParentWnd)
{
::SendMessage(MsgBox.hParentWnd, WM_GETTEXT, MAX_PATH, (LPARAM)tchCaption);
MsgBox.lpszCaption = tchCaption;
} //if
if ((NULL == MsgBox.lpszCaption) || (0 == MsgBox.lpszCaption [0]))
MsgBox.lpszCaption = _T("Error");
} //if
#ifdef PPMSGBOX_DO_NOT_SAVE_CHECKBOX
//ENG: Checks a states of the "DonNotAskAgain" checkboxes
//RUS: �������� ��������� ������ "�����������������"
if ((MsgBox.dwStyle & MB_CHECKBOX))
{
if ((NULL != MsgBox.lpszModuleName) && (0 != MsgBox.lpszModuleName [0]))
{
//ENG: Default value of PPMessageBox return code (checkbox wasn't checked)
//RUS: �������� ���� �������� PPMessageBox ��-��������� (������ �� ��� ����������)
DWORD dwData = 0;
//ENG: Get full path of the current module
//RUS: �������� ������ ���� � ������������ ������
TCHAR szModule[_MAX_PATH];
::GetModuleFileName(NULL, szModule, _MAX_PATH);
TCHAR szPath[MAX_PATH];
LPTSTR lpFilePart;
::GetFullPathName(szModule, _MAX_PATH, szPath, &lpFilePart);
//ENG: Creates a key value
//RUS: ������� �������� �����
CPPString sDoNotAskKey;
sDoNotAskKey.Format(_T("%s%d"), MsgBox.lpszModuleName, MsgBox.nLine);
#ifdef PPMSGBOX_USE_PROFILE_FILE
//ENG: An info will be search in the INI file
//RUS: ����� ���������� ����� ���������� � INI �����
//ENG: Removes a module name from path
//RUS: ������� ��� ������ �� ����
if (NULL != lpFilePart)
*(lpFilePart) = _T('\0');
//ENG: Add an INI filename to path
//RUS: ��������� ��� INI ����� � ����
_tcscat(szPath, PPMSGBOX_INI_FILE);
const nHexStringLength = 16;
TCHAR szBuf[nHexStringLength];
//ENG: Get a return code of PPMessageBox as HEX string
//RUS: �������� ��� ������� ������� PPMessageBox � ������� HEX ������
if (::GetPrivateProfileString(_T("DoNotAsk"), // section name
sDoNotAskKey, // key name
_T(""), // default string
szBuf, // destination buffer
nHexStringLength,// size of destination buffer
szPath)) // initialization file name
{
//ENG: Convert from HEX string to DWORD value
//RUS: �������������� HEX ������ � DWORD �����
dwData = _tcstoul(szBuf, NULL, 16);
} //if
#else
//ENG: An info will be search in the system registry
//RUS: ����� ���������� ����� ���������� � ��������� �������
CPPString sSection;
if ((NULL == MsgBox.lpszCompanyName) || (0 == MsgBox.lpszCompanyName [0]))
sSection.Format(_T("Software\\%s\\%s"), lpFilePart, PPMSGBOX_REGISTRY_KEY);
else
sSection.Format(_T("Software\\%s\\%s\\%s"), MsgBox.lpszCompanyName, lpFilePart, PPMSGBOX_REGISTRY_KEY);
//ENG: Read a value from registry
//RUS: ���������� �������� �� �������
HKEY hKey = NULL;
LONG lRet = ::RegOpenKeyEx(HKEY_CURRENT_USER, sSection, 0, KEY_READ, &hKey);
if (lRet == ERROR_SUCCESS)
{
DWORD dwType = 0;
DWORD dwSize = sizeof(DWORD);
lRet = ::RegQueryValueEx(hKey, sDoNotAskKey, 0, &dwType, (LPBYTE)&dwData, &dwSize);
::RegCloseKey(hKey);
if (lRet != ERROR_SUCCESS)
dwData = 0;
} //if
#endif //PPMSGBOX_USE_PROFILE_FILE
//ENG: If "DoNotAsk" flag was checked
//RUS: ���� ������ "������������" ����������
if (dwData)
return (int)dwData;
} //if
} //if
#endif //PPMSGBOX_DO_NOT_SAVE_CHECKBOX
if ((MsgBox.dwStyle & MB_NOSOUND) == 0)
::MessageBeep(MsgBox.dwStyle & MB_ICONMASK);
CPPMessageBoxTemplate Dlg(&MsgBox);
int nResult = Dlg.Display();
return nResult;
} //End of PPMessageBoxIndirect
CPPMessageBoxTemplate::CPPMessageBoxTemplate(const PPMSGBOXPARAMS *pMsgBox)
{
m_MsgParam = *pMsgBox;
if (NULL == m_MsgParam.hInstanceStrings)
m_MsgParam.hInstanceStrings = ::GetModuleHandle(NULL);
if (NULL == m_MsgParam.hInstanceIcons)
m_MsgParam.hInstanceIcons = ::GetModuleHandle(NULL);
m_hBitmapBk = NULL;
m_bMoreInfoOpened = FALSE;
m_dwMoreInfoHeight = 0;
m_sDisabledCaption.Empty();
m_sTimeoutText.Empty();
m_sMoreInfoClosed.Empty();
m_sMoreInfoOpened.Empty();
m_sHeader.Empty();
m_sCaption = GetString(m_MsgParam.lpszCaption);
m_sText.Empty();
m_vecButtons.clear();
// m_mapBtnText.clear();
NONCLIENTMETRICS ncm;
memset(&ncm, 0, sizeof(ncm));
ncm.cbSize = sizeof(ncm);
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
m_hFont = ::CreateFontIndirect(&ncm.lfMessageFont);
//Load a default icon
m_hIcon = NULL;
switch (m_MsgParam.dwStyle & MB_ICONMASK)
{
case MB_ICONERROR:
m_hIcon = ::LoadIcon(NULL, IDI_ERROR);
break;
case MB_ICONQUESTION:
m_hIcon = ::LoadIcon(NULL, IDI_QUESTION);
break;
case MB_ICONEXCLAMATION:
m_hIcon = ::LoadIcon(NULL, IDI_EXCLAMATION);
break;
case MB_ICONASTERISK:
m_hIcon = ::LoadIcon(NULL, IDI_ASTERISK);
break;
case MB_USERICON:
if (NULL != m_MsgParam.lpszIcon)
{
m_hIcon = (HICON)::LoadImage(m_MsgParam.hInstanceIcons, m_MsgParam.lpszIcon,
IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
} //if
break;
} //switch
//Setup a sizes
m_dwSizes [PPMSGBOX_SIZE_SEPX] = 5;
m_dwSizes [PPMSGBOX_SIZE_MSGX] = 14;
m_dwSizes [PPMSGBOX_SIZE_MSGY] = 14;
// m_dwSizes [PPMSGBOX_SIZE_BTNX] = 90;
// m_dwSizes [PPMSGBOX_SIZE_BTNY] = 23;
m_dwSizes [PPMSGBOX_SIZE_CHKX] = 10;
m_dwSizes [PPMSGBOX_SIZE_CHKY] = 13;
m_dwSizes [PPMSGBOX_SIZE_CTRLX] = 11;
m_dwSizes [PPMSGBOX_SIZE_CTRLY] = 11;
/* //Customizes a button's text
SetButtonText(IDOK, _T("OK"), IDS_OK);
SetButtonText(IDCANCEL, _T("Cancel"), IDS_CANCEL);
SetButtonText(IDABORT, _T("Abort"), IDS_ABORT);
SetButtonText(IDRETRY, _T("Retry"), IDS_RETRY);
SetButtonText(IDIGNORE, _T("Ignore"), IDS_IGNORE);
SetButtonText(IDYES, _T("Yes"), IDS_YES);
SetButtonText(IDNO, _T("No"), IDS_NO);
SetButtonText(IDCLOSE, _T("Close"), 0);
SetButtonText(IDHELP, _T("Help"), IDS_HELP);
SetButtonText(IDTRYAGAIN, _T("Try Again"), IDS_TRYAGAIN);
SetButtonText(IDCONTINUE, _T("Continue"), IDS_CONTINUE);
SetButtonText(IDSKIP, _T("Skip"), IDS_SKIP);
SetButtonText(IDSKIPALL, _T("Skip All"), IDS_SKIPALL);
SetButtonText(IDIGNOREALL, _T("Ignore All"), IDS_IGNORE);
SetButtonText(IDYESTOALL, _T("Yes to All"), IDS_YESTOALL);
SetButtonText(IDNOTOALL, _T("No to All"), IDS_NOTOALL);
if (m_MsgParam.sCheckBoxText.IsEmpty())
SetButtonText(MB_CHECKBOX, _T("Do not show again"), IDS_DONOTSHOWAGAIN);
else
SetButtonText(MB_CHECKBOX, m_MsgParam.sCheckBoxText, IDS_DONOTSHOWAGAIN);*/
} //End of CPPMessageBoxTemplate
CPPMessageBoxTemplate::~CPPMessageBoxTemplate()
{
if (NULL != m_hFont)
::DeleteObject(m_hFont);
if (NULL != m_hBitmapBk)
::DeleteObject(m_hBitmapBk);
if (NULL != m_hIcon)
::DeleteObject(m_hIcon);
RemoveAllButtons();
} //End of ~CPPMessageBoxTemplate
int CPPMessageBoxTemplate::Display()
{
LPDLGTEMPLATE pdlg;
HGLOBAL hgbl = GlobalAlloc(GMEM_ZEROINIT, sizeof(DLGTEMPLATE)*2);
_ASSERT(hgbl);
if (NULL == hgbl)
return IDCANCEL;
pdlg = (LPDLGTEMPLATE)GlobalLock(hgbl);
_ASSERT(pdlg);
if (NULL == hgbl)
{
GlobalFree(hgbl);
return IDCANCEL;
} //if
pdlg->x = 0;
pdlg->y = 0;
pdlg->cx = 100;
pdlg->cy = 100;
pdlg->style = DS_MODALFRAME|WS_VISIBLE|WS_POPUP|WS_BORDER|WS_CAPTION|WS_SYSMENU|DS_CENTER;
pdlg->dwExtendedStyle = 0;
pdlg->cdit = 0;
HINSTANCE hInstance = ::GetModuleHandle(NULL);
int nResult = ::DialogBoxIndirectParam(hInstance, pdlg, m_MsgParam.hParentWnd, MsgBoxDlgProc, (LPARAM)this);
GlobalUnlock(pdlg);
GlobalFree(hgbl);
return nResult;
} //End of PPMessageBox
//subclassing a checkbox
//LRESULT CALLBACK NewCheckBoxProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); // prototype for the combo box subclass proc
//WNDPROC lpfnOrgCheckboxProc;
///////////////////////////////////////////////////////////////////////////////
// MsgBoxDlgProc
BOOL CALLBACK CPPMessageBoxTemplate::MsgBoxDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
CPPMessageBoxTemplate * pDlg = (CPPMessageBoxTemplate*)::GetWindowLong(hwnd, GWL_USERDATA);
switch (message)
{
case WM_INITDIALOG:
{
::SetWindowLong(hwnd, GWL_USERDATA, lParam); // save it for the others
pDlg = (CPPMessageBoxTemplate*)lParam;
_ASSERTE(pDlg);
pDlg->OnInitDialog(hwnd);
if (NULL != pDlg->m_stCheckBtn.hWnd)
{
//Subclassing a checkbox
// lpfnOrgCheckboxProc = (WNDPROC)::SetWindowLongPtr(
// pDlg->m_stCheckBtn.hWnd,
// GWL_WNDPROC,
// (LONG)NewCheckBoxProc);
} //if
return FALSE;
} //End of case WM_INITDIALOG
case WM_DESTROY:
{
// if (NULL != pDlg->m_stCheckBtn.hWnd)
// {
// //Unsubclassing a checkbox
// ::SetWindowLongPtr(pDlg->m_stCheckBtn.hWnd,
// GWL_WNDPROC, (LONG)lpfnOrgCheckboxProc);
// } //if
pDlg->RemoveAllButtons();
return FALSE;
} //End of case WM_DESTROY
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
pDlg->DrawBox(hwnd, ps.hdc);
EndPaint(hwnd, &ps);
return FALSE;
} //End of case WM_PAINT
case WM_COMMAND:
{
//ENG: Get a clicked button ID
//RUS: �������� ID ������� ������
DWORD dwBtnID = LOWORD(wParam);
if(dwBtnID)
{
//ENG: Disable VK_ESCAPE if "Cancel" button is not present in messagebox
//RUS: ��������� ������ VK_ESCAPE ���� ������ "������" �� ������������
if ((IDCANCEL == dwBtnID) && !pDlg->m_bIsCancelExist)
return FALSE;
switch (dwBtnID)
{
case IDHELP:
{
TCHAR szBuf[_MAX_PATH];
memset(&szBuf, 0, sizeof(szBuf));
::GetModuleFileName(NULL, szBuf, _MAX_PATH);
if (_tcslen(szBuf) > 0)
{
//searching a last dot char '.'
TCHAR *cp = _tcsrchr(szBuf, _T('.'));
if (cp)
{
_tcscpy(cp, _T(".hlp"));
//Call a context help
::WinHelp(hwnd, szBuf,
(pDlg->m_MsgParam.dwContextHelpID == 0) ? HELP_PARTIALKEY : HELP_CONTEXT,
pDlg->m_MsgParam.dwContextHelpID);
} //if
} //if
return FALSE;
}
case IDMOREINFO_CLOSED:
case IDMOREINFO_OPENED:
{
RECT rcWindow;
::GetWindowRect(hwnd, &rcWindow);
DWORD dwHeight = rcWindow.bottom - rcWindow.top;
for (DWORD i = 0; i < pDlg->m_vecButtons.size(); ++i)
{
STRUCT_BUTTONS & sbTemp = pDlg->m_vecButtons [i];
if (IDMOREINFO_CLOSED == sbTemp.nTypeBtn)
{
if (pDlg->m_bMoreInfoOpened)
{
pDlg->m_bMoreInfoOpened = FALSE;
dwHeight -= pDlg->m_dwMoreInfoHeight;
::SendMessage(sbTemp.hWnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDlg->m_sMoreInfoClosed);
}
else
{
pDlg->m_bMoreInfoOpened = TRUE;
dwHeight += pDlg->m_dwMoreInfoHeight;
::SendMessage(sbTemp.hWnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)pDlg->m_sMoreInfoOpened);
} //if
::MoveWindow(hwnd, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, dwHeight, TRUE);
} //if
} //for
return FALSE;
}
case IDREPORT:
{
if ((pDlg->m_MsgParam.dwReportMsgID) && (NULL != pDlg->m_MsgParam.hParentWnd))
::SendMessage(pDlg->m_MsgParam.hParentWnd, pDlg->m_MsgParam.dwReportMsgID, 0, 0);
return FALSE;
}
default:
{
//ENG: Stop of timer
//RUS: ������� �������
::KillTimer(hwnd, 1);
//ENG: Handles a checkbox state
//RUS: ������������ ��������� checkbox
if (NULL != pDlg->m_stCheckBtn.hWnd)
{
//ENG: Toggles a checkbox state
//RUS: ����������� ��������� checkbox
LRESULT nCheck = ::SendMessage(pDlg->m_stCheckBtn.hWnd, BM_GETCHECK, 0, 0);
if (BST_CHECKED == nCheck)
{
dwBtnID |= pDlg->m_MsgParam.dwStyle & MB_CHECKBOXCHECKED;
#ifdef PPMSGBOX_DO_NOT_SAVE_CHECKBOX
if ((NULL != pDlg->m_MsgParam.lpszModuleName) && (0 != pDlg->m_MsgParam.lpszModuleName [0]))
{
//ENG: Get full path of the current module
//RUS: �������� ������ ���� � ������������ ������
TCHAR szModule[_MAX_PATH];
::GetModuleFileName(NULL, szModule, _MAX_PATH);
TCHAR szPath[_MAX_PATH];
LPTSTR lpFilePart;
::GetFullPathName(szModule, _MAX_PATH, szPath, &lpFilePart);
//ENG: Creates a key value
//RUS: ������� �������� �����
CPPString sDoNotAskKey;
sDoNotAskKey.Format(_T("%s%d"), pDlg->m_MsgParam.lpszModuleName, pDlg->m_MsgParam.nLine);
#ifdef PPMSGBOX_USE_PROFILE_FILE
//ENG: An info will be search in the INI file
//RUS: ����� ���������� ����� ���������� � INI �����
//ENG: Removes a module name from path
//RUS: ������� ��� ������ �� ����
if (NULL != lpFilePart)
*(lpFilePart) = _T('\0');
//ENG: Add an INI filename to path
//RUS: ��������� ��� INI ����� � ����
_tcscat(szPath, PPMSGBOX_INI_FILE);
CPPString sData;
sData.Format(_T("0x%08X"), dwBtnID);
::WritePrivateProfileString(_T("DoNotAsk"), // section name
sDoNotAskKey, // key name
sData, // string to add
szPath); // initialization file
#else
//ENG: An info will be search in the system registry
//RUS: ����� ���������� ����� ���������� � ��������� �������
CPPString sSection;
if ((NULL == pDlg->m_MsgParam.lpszCompanyName) || (0 == pDlg->m_MsgParam.lpszCompanyName [0]))
sSection.Format(_T("Software\\%s\\%s"), lpFilePart, PPMSGBOX_REGISTRY_KEY);
else
sSection.Format(_T("Software\\%s\\%s\\%s"), pDlg->m_MsgParam.lpszCompanyName, lpFilePart, PPMSGBOX_REGISTRY_KEY);
//ENG: Stores a checkbox state
//RUS: ��������� ��������� checkbox
DWORD dwResult = 0;
HKEY hKey = NULL;
LONG lRet = ::RegCreateKeyEx(HKEY_CURRENT_USER, sSection, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwResult);
if (lRet == ERROR_SUCCESS)
{
::RegSetValueEx(hKey, sDoNotAskKey, 0, REG_DWORD,
(const BYTE *) &dwBtnID, sizeof(DWORD));
::RegCloseKey(hKey);
} //if
#endif //PPMSGBOX_USE_PROFILE_FILE
} //if
#endif //PPMSGBOX_DO_NOT_SAVE_CHECKBOX
} //if
} //if
//ENG: Close a message box and return code
//RUS: ��������� ������ � ���������� ���
::EndDialog(hwnd, dwBtnID);
return TRUE;
}
} //switch
} //if
} //End of case WM_COMMAND
break;
case WM_TIMER: // used for timeout
{
if (wParam == 1)
{
pDlg->OnTimer(hwnd);
return TRUE;
} //if
return FALSE;
} //End of case WM_TIMER
break;
case WM_CTLCOLORSTATIC:
{
//ENG: For a transparent text of the checkbox
//RUS: ��� ������������ ������ checkbox
::SetBkMode((HDC)wParam, TRANSPARENT);
return (BOOL)::GetStockObject(NULL_BRUSH);
} //End of case WM_CTLCOLORSTATIC
break;
case WM_SETCURSOR:
{
POINT point;
::GetCursorPos(&point);
::ScreenToClient(hwnd, &point);
if (pDlg->m_dwHeaderHeight)
{
if (pDlg->m_pHeader.OnSetCursor(&point))
return TRUE; //The cursor over the hyperlink
} //if
if (pDlg->m_dwMessageHeight)
{
if (pDlg->m_pDrawer.OnSetCursor(&point))
return TRUE; //The cursor over the hyperlink
} //if
if (pDlg->m_dwMoreInfoHeight)
{
if (pDlg->m_pMoreInfo.OnSetCursor(&point))
return TRUE; //The cursor over the hyperlink
} //if
} //End of case WM_SETCURSOR
break;
case WM_LBUTTONDOWN:
{
POINT point = {LOWORD(lParam), HIWORD(lParam)};
if (pDlg->m_dwHeaderHeight)
pDlg->m_pHeader.OnLButtonDown(&point);
if (pDlg->m_dwMessageHeight)
pDlg->m_pDrawer.OnLButtonDown(&point);
if (pDlg->m_dwMoreInfoHeight)
pDlg->m_pMoreInfo.OnLButtonDown(&point);
} //End of case WM_LBUTTONDOWN
break;
case WM_ERASEBKGND:
{
return TRUE;
} //End of case WM_ERASEBKGND
case UDM_HTMLDRAWER_REPAINT:
{
pDlg->DrawBox(hwnd, NULL);
//::InvalidateRect(hwnd, NULL, FALSE);
return TRUE;
} //End of case UDM_HTMLDRAWER_REPAINT
// case WM_LBUTTONDOWN:
// {
// //ENG: If a checkbox window is exist
// //RUS: ���� checkbox ����������
// if ((NULL != pDlg->m_stCheckText.hWnd) && (NULL != pDlg->m_stCheckBtn.hWnd))
// {
// //ENG: Get a child window
// //RUS: �������� �������� ����
// POINT pt;
// pt.x = LOWORD(lParam);
// pt.y = HIWORD(lParam);
// HWND hWndClient = ::ChildWindowFromPoint(hwnd, pt);
// if (pDlg->m_stCheckText.hWnd == hWndClient)
// {
// //ENG: Toggles a checkbox state
// //RUS: ����������� ��������� checkbox
// LRESULT nCheck = ::SendMessage(pDlg->m_stCheckBtn.hWnd, BM_GETCHECK, 0, 0);
// if (nCheck == BST_CHECKED)
// ::SendMessage(pDlg->m_stCheckBtn.hWnd, BM_SETCHECK, BST_UNCHECKED, 0);
// else if (nCheck == BST_UNCHECKED)
// ::SendMessage(pDlg->m_stCheckBtn.hWnd, BM_SETCHECK, BST_CHECKED, 0);
// return TRUE;
// } //if
// } //if
// } //End of case WM_LBUTTONDOWN
// break;
} //switch
return FALSE;
}
/*
BOOL m_bIsFocusedCheckBox(FALSE);
LRESULT CALLBACK NewCheckBoxProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_ERASEBKGND:
{
TRACE ("WM_ERASEBKGND\n");
m_bIsFocusedCheckBox = FALSE;
}
case WM_SETFOCUS:
break;
case WM_KILLFOCUS:
// ::SendMessage(hwnd, WM_PAINT, 0, 0);
break;
// case WM_DRAWITEM:
// {
// LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
//
// BOOL bIsPressed = (lpDIS->itemState & ODS_SELECTED);
// BOOL bIsFocused = (lpDIS->itemState & ODS_FOCUS);
//
// RECT rcClient = lpDIS->rcItem;
// ::SetBkMode(lpDIS->hDC, TRANSPARENT);
//
// RECT rcBox;
// rcBox.left = rcClient.left;
// rcBox.top = rcClient.top;
// rcBox.right = rcBox.left + 13;
// rcBox.bottom = rcBox.top + 13;
// ::DrawFrameControl(lpDIS->hDC, &rcBox, DFC_BUTTON, DFCS_BUTTONCHECK);
//
// return TRUE;
// }
case WM_PAINT:
{
TRACE ("WM_PAINT\n");
RECT rect;
::GetClientRect(hwnd, &rect);
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hwnd, &ps);
UINT uState = ::SendMessage(hwnd, BM_GETSTATE, 0, 0);
TCHAR szText [_MAX_PATH];
int nCount = ::SendMessage(hwnd, WM_GETTEXT, _MAX_PATH, (WPARAM)szText);
HFONT hFont = (HFONT)::SendMessage(hwnd, WM_GETFONT, 0, 0);
HFONT hOldFont = (HFONT)::SelectObject(hDC, hFont);
int nOldBkMode = ::SetBkMode(hDC, TRANSPARENT);
RECT rcCheck = rect;
rcCheck.right = rcCheck.left + rcCheck.bottom - rcCheck.top;
if (uState & BST_CHECKED)
::DrawFrameControl(hDC, &rcCheck, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_CHECKED | DFCS_HOT);
else
::DrawFrameControl(hDC, &rcCheck, DFC_BUTTON, DFCS_BUTTONCHECK | DFCS_HOT);
rect.left = rcCheck.right + 6;
::DrawText(hDC, szText, nCount, &rect, DT_SINGLELINE|DT_LEFT|DT_VCENTER);
// ::TextOut(hDC, 19, 0, szText, nCount);
rect.left -= 2;
rect.top -= 1;
rect.right += 2;
rect.bottom += 1;
// if ((uState & BST_FOCUS) && !m_bIsFocusedCheckBox)
// {
// TRACE ("WM_FOCUS\n");
// m_bIsFocusedCheckBox = TRUE;
// ::DrawFocusRect(hDC, &rect);
// }
// else if (!(uState & BST_FOCUS) && m_bIsFocusedCheckBox)
// {
// TRACE ("WM_UNFOCUS\n");
// m_bIsFocusedCheckBox = FALSE;
// ::DrawFocusRect(hDC, &rect);
// }
// ::Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom);
::SetBkMode(hDC, nOldBkMode);
::SelectObject(hDC, hOldFont);
EndPaint(hwnd, &ps);
return TRUE;
}
}
return CallWindowProc(lpfnOrgCheckboxProc, hwnd, message, wParam, lParam);
} //End of NewCheckBoxProc
*/
void CPPMessageBoxTemplate::OnTimer(HWND hwnd)
{
//Gets info about default button
STRUCT_BUTTONS & sb = m_vecButtons [m_nDefBtn];
if (m_dwCountdownTimer > 0)
{
m_dwCountdownTimer--;
if (m_dwCountdownTimer > 0)
{
//Time was not complete
CPPString str;
if ((m_MsgParam.nDisabledSeconds > 0) && (m_MsgParam.bDisableAllCtrls))
{
str.Format(m_sDisabledCaption, m_sCaption, m_dwCountdownTimer);
::SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)str);
return;
}
else
{
str.Format(PPMSGBOX_BUTTON_DISABLED, m_sTimeoutText, m_dwCountdownTimer);
::SendMessage(sb.hWnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)str);
return;
} //if
} //if
} //if
//ENG: Stop timer
//RUS: ������������� ������
::KillTimer(hwnd, 1);
if (m_MsgParam.nDisabledSeconds > 0)
{
//ENG: Enable a system menu if Cancel button exist
//RUS: ��������� ��������� ���� ���� ������ ������ ����������
if (m_bIsCancelExist)
::EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE, MF_ENABLED);
if (m_MsgParam.bDisableAllCtrls)
{
//ENG: Set a caption text
//RUS: ������������� ����� ���������
::SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)m_sCaption);
//ENG: Enables all buttons except default button
//RUS: ��������� ��� ������ ����� ������ �� ���������
for (UINT i = 0; i < m_vecButtons.size(); ++i)
{
if (i != m_nDefBtn)
{
STRUCT_BUTTONS & sbTemp = m_vecButtons [i];
LONG nStyle = ::GetWindowLong(sbTemp.hWnd, GWL_STYLE);
nStyle &= ~WS_DISABLED;
::SetWindowLong(sbTemp.hWnd, GWL_STYLE, nStyle);
::SendMessage(sbTemp.hWnd, WM_ENABLE, 1, 0);
} //if
} //for
}
else
{
//ENG: Set a real text on the default button only
//RUS: ������������� �������� ����� ������ ������ �� ���������
::SendMessage(sb.hWnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)m_sTimeoutText);
} //if
//ENG: Enable a default button and set it to default
//RUS: ��������� ������ �� ��������� � ������������� �� �� ���������
LONG nStyle = ::GetWindowLong(sb.hWnd, GWL_STYLE);
nStyle &= ~WS_DISABLED;
nStyle |= BS_DEFPUSHBUTTON;
::SetWindowLong(sb.hWnd, GWL_STYLE, nStyle);
::SendMessage(sb.hWnd, WM_ENABLE, 1, 0);
}
else if (m_MsgParam.nTimeoutSeconds > 0)
{
//ENG: Set a real text on the default button only
//RUS: ������������� �������� ����� ������ ������ �� ���������
::SendMessage(sb.hWnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)m_sTimeoutText);
//ENG: Imitation to click on default button
//RUS: �������� ������� ������ �� ���������
::SendMessage(hwnd, WM_COMMAND, sb.nTypeBtn | MB_TIMEOUT, 0);
} //if
} //End of OnTimer
void CPPMessageBoxTemplate::OnInitDialog(HWND hwnd)
{
//ENG: Setup a timer
//RUS: ��������� �������
m_dwCountdownTimer = 0;
if (m_MsgParam.nDisabledSeconds > 0)
m_dwCountdownTimer = m_MsgParam.nDisabledSeconds;
if (m_MsgParam.nTimeoutSeconds > 0)
m_dwCountdownTimer = m_MsgParam.nTimeoutSeconds;
m_pHeader.SetCallbackRepaint(hwnd, UDM_HTMLDRAWER_REPAINT);
m_pDrawer.SetCallbackRepaint(hwnd, UDM_HTMLDRAWER_REPAINT);
m_pMoreInfo.SetCallbackRepaint(hwnd, UDM_HTMLDRAWER_REPAINT);
CPPString str;
m_sText = GetString(m_MsgParam.lpszText);
if (m_MsgParam.dwStyle & MB_RIGHT)
str.Format(_T("<right>%s</right>"), m_sText);
else
str = m_sText;
int nSysIconWidth = ::GetSystemMetrics(SM_CXICON);
if (NULL != m_hIcon)
m_sText.Format(_T("<table cellpadding=%d><tr><td width=%d><icon handle=0x%X></td><td>%s</td></tr></table>"), m_dwSizes [PPMSGBOX_SIZE_SEPX], nSysIconWidth, m_hIcon, str);
else
m_sText = str;//.Format(_T("<table><tr><td>%s</td></tr></table>"), str);
SIZE sz = PrepareMessageBox(hwnd);
//Set a message box caption
BOOL bGrayedClose = m_bIsCancelExist ? FALSE : TRUE;
str = m_sCaption;
if (m_MsgParam.nDisabledSeconds > 0)
{
if (m_MsgParam.bDisableAllCtrls)
{
m_sDisabledCaption = GetLocalizedButtonText(MB_TIMEOUT);
str.Format(m_sDisabledCaption, m_sCaption, m_dwCountdownTimer);
bGrayedClose = TRUE;
}
else
{
STRUCT_BUTTONS & sb = m_vecButtons [m_nDefBtn];
if (IDCANCEL == sb.nTypeBtn)
bGrayedClose = TRUE;
} //if
} //if
::SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)str);
//Disable a menu
if (bGrayedClose)
::EnableMenuItem(GetSystemMenu(hwnd, FALSE), SC_CLOSE, MF_GRAYED);
//Centering of the dialog
RECT rcParent;
if (NULL != GetParent(hwnd))
::GetWindowRect(::GetParent(hwnd), &rcParent);
else
{
rcParent.left = 0;
rcParent.top = 0;
rcParent.right = ::GetSystemMetrics(SM_CXSCREEN);
rcParent.bottom = ::GetSystemMetrics(SM_CYSCREEN);
} //if
::MoveWindow(hwnd, rcParent.left + (rcParent.right - rcParent.left - sz.cx) / 2,
rcParent.top + (rcParent.bottom - rcParent.top - sz.cy) / 2,
sz.cx, sz.cy, TRUE);
//ENG: Gets a size of the client area of the messagebox
//RUS: �������� ������� ���������� ������� messagebox
RECT rcClient;
::GetClientRect(hwnd, &rcClient);
//ENG: Calculates a full width of all buttons
//RUS: ��������� ������, ���������� ����� ��������
int nWidth = m_vecButtons.size() * (m_dwSizes [PPMSGBOX_SIZE_BTNX] + m_dwSizes [PPMSGBOX_SIZE_CTRLX]) - m_dwSizes [PPMSGBOX_SIZE_CTRLX];
RECT rcBtn = rcClient;
rcBtn.bottom -= m_dwSizes [PPMSGBOX_SIZE_CTRLY];
if ((m_MsgParam.dwStyle & MB_CHECKBOX) && (m_MsgParam.dwStyle & MB_CHECKBOXUNDERBUTTONS))
rcBtn.bottom -= m_dwSizes [PPMSGBOX_SIZE_CTRLY] + m_dwSizes [PPMSGBOX_SIZE_CHKY];
rcBtn.top = rcBtn.bottom - m_dwSizes [PPMSGBOX_SIZE_BTNY];
switch (m_MsgParam.nControlsAlign)
{
case PPMSGBOX_ALIGN_LEFT:
rcBtn.left += m_dwSizes [PPMSGBOX_SIZE_CTRLX];
break;
case PPMSGBOX_ALIGN_RIGHT:
rcBtn.left = rcBtn.right - m_dwSizes [PPMSGBOX_SIZE_CTRLX] - nWidth;
break;
case PPMSGBOX_ALIGN_CENTER:
default:
rcBtn.left += (rcBtn.right - rcBtn.left - nWidth) / 2;
break;
} //switch
//Create buttons
for (UINT i = 0; i < m_vecButtons.size(); ++i)
{
//ENG: Get a right edge of the button
//RUS: ��������� ���������� ������ ������� ������
rcBtn.right = rcBtn.left + m_dwSizes [PPMSGBOX_SIZE_BTNX];
STRUCT_BUTTONS & sb = m_vecButtons [i];
//ENG: Create a button
//RUS: ������� ������
::MoveWindow(sb.hWnd, rcBtn.left, rcBtn.top, m_dwSizes [PPMSGBOX_SIZE_BTNX], m_dwSizes [PPMSGBOX_SIZE_BTNY], TRUE);
//ENG: Jump to the left edge of the next button
//RUS: ������������ � ������� ������ ���� ��������� ������
rcBtn.left += m_dwSizes [PPMSGBOX_SIZE_BTNX] + m_dwSizes [PPMSGBOX_SIZE_CTRLX];
} //for
//ENG: Create a checkbox
//RUS: ������� checkbox
if (m_stCheckBtn.nTypeBtn)
{
//ENG: Gets a text of the checkbox
//RUS: �������� ����� checkbox
// CPPString sCheckText = GetButtonText(m_stCheckBtn.nTypeBtn);
//Creates a checkbox control
rcBtn = rcClient;
rcBtn.bottom -= m_dwSizes [PPMSGBOX_SIZE_CTRLY];
if (!(m_MsgParam.dwStyle & MB_CHECKBOXUNDERBUTTONS))
rcBtn.bottom -= m_dwSizes [PPMSGBOX_SIZE_CTRLY] + m_dwSizes [PPMSGBOX_SIZE_BTNY];
rcBtn.top = rcBtn.bottom - m_dwSizes [PPMSGBOX_SIZE_CHKY];
rcBtn.left += m_dwSizes [PPMSGBOX_SIZE_CHKX];
::MoveWindow(m_stCheckBtn.hWnd, rcBtn.left, rcBtn.top, m_dwSizes [PPMSGBOX_SIZE_CHKY], // + m_dwSizes [PPMSGBOX_SIZE_CHKY] / 2 + sz.cx,
m_dwSizes [PPMSGBOX_SIZE_CHKY], TRUE);
//ENG: To the transparency output of the text of the checkbox
//RUS: ����� ��� checkbox ������� �������� ��� ����������� ������
rcBtn.left += m_dwSizes [PPMSGBOX_SIZE_CHKY] + m_dwSizes [PPMSGBOX_SIZE_CHKY] / 2;
RECT rcCheck;
::GetWindowRect(m_stCheckText.hWnd, &rcCheck);
::MoveWindow(m_stCheckText.hWnd, rcBtn.left, rcBtn.top, rcCheck.right - rcCheck.left,
rcCheck.bottom - rcCheck.top, TRUE);
} //if
//ENG: The message box is created with the WS_EX_TOPMOST window style
if (m_MsgParam.dwStyle & MB_TOPMOST)
::SetWindowPos(hwnd, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE);
//ENG: The message box becomes the foreground window
if (m_MsgParam.dwStyle & MB_SETFOREGROUND)
::SetForegroundWindow(hwnd);
//ENG: The countdown timer is enabled
//RUS: ������ ��������� ������� ������������
if (m_dwCountdownTimer > 0)
::SetTimer(hwnd, 1, 1000, NULL);
} //End of OnInitDialog
CPPString CPPMessageBoxTemplate::GetString(LPCTSTR lpszText)
{
if ((NULL == lpszText) || (0 == lpszText [0]))
return _T("");
CPPString sText = _T("");
if (0 == HIWORD(lpszText))
{
//lpszText is a MAKEINTRESOURCE(ID) of the text from the resources
if ((NULL != m_MsgParam.hInstanceStrings) && !(m_MsgParam.dwStyle & MB_NORESOURCE))
{
TCHAR tchText [_MAX_PATH];
int nCount = ::LoadString(m_MsgParam.hInstanceStrings, (UINT)lpszText, tchText, _MAX_PATH);
if (nCount)
sText = (CPPString)tchText;
} //if
}
else
{
//lpszText is a pointer to the button text
sText = (CPPString)lpszText;
} //if
return sText;
} //End of GetString
CPPString CPPMessageBoxTemplate::GetLocalizedButtonText(DWORD dwBtnID, CPPString sDefText /*=_T("")*/)
{
DWORD dwResID = 0;
CPPString sText = _T("");
switch (dwBtnID)
{
case IDOK:
dwResID = IDS_OK;
sText = _T("OK");
break;
case IDCANCEL:
dwResID = IDS_CANCEL;
sText = _T("Cancel");
break;
case IDIGNORE:
dwResID = IDS_IGNORE;
sText = _T("Ignore");
break;
case IDRETRY:
dwResID = IDS_RETRY;
sText = _T("Retry");
break;
case IDABORT:
dwResID = IDS_ABORT;
sText = _T("Abort");
break;
case IDHELP:
dwResID = IDS_HELP;
sText = _T("Help");
break;
case IDYES:
dwResID = IDS_YES;
sText = _T("Yes");
break;
case IDNO:
dwResID = IDS_NO;
sText = _T("No");
break;
case IDCONTINUE:
dwResID = IDS_CONTINUE;
sText = _T("Continue");
break;
case IDYESTOALL:
dwResID = IDS_YESTOALL;
sText = _T("Yes to all");
break;
case IDNOTOALL:
dwResID = IDS_NOTOALL;
sText = _T("No to all");
break;
case IDTRYAGAIN:
dwResID = IDS_TRYAGAIN;
sText = _T("Try again");
break;
case IDREPORT:
dwResID = IDS_REPORT;
sText = _T("Report");
break;
case IDIGNOREALL:
dwResID = IDS_IGNOREALL;
sText = _T("Ignore all");
break;
case IDSKIP:
dwResID = IDS_SKIP;
sText = _T("Skip");
break;
case IDSKIPALL:
dwResID = IDS_SKIPALL;
sText = _T("Skip all");
break;
case MB_CHECKBOX:
dwResID = IDS_DONOTSHOWAGAIN;
sText = _T("Do not show again");
break;
case IDMOREINFO_OPENED:
dwResID = IDS_MOREINFO_OPENED;
sText = _T("<< More");
break;
case IDMOREINFO_CLOSED:
dwResID = IDS_MOREINFO_CLOSED;
sText = _T("More >>");
break;
case MB_TIMEOUT:
dwResID = IDS_GLOBALDISABLE;
sText = _T("%s (%d seconds remaining)");
break;
} //switch
if (sDefText.IsEmpty())
sDefText = sText;
sText.Empty();
//Try to get a localized button text from the specified resources or from the pointer
//to real text
if (NULL != m_MsgParam.pLocalBtnText)
{
typedef mapLocalBtnText::iterator iterLocalBtnText;
iterLocalBtnText iterMap = m_MsgParam.pLocalBtnText->find(dwBtnID);
if (iterMap != m_MsgParam.pLocalBtnText->end())
{
LPCTSTR lpszText = iterMap->second;
sText = GetString(lpszText);
/* if (0 == HIWORD(lpszText))
{
//lpszText is a MAKEINTRESOURCE() of the buton text from the resources
if ((NULL != m_MsgParam.hInstanceStrings) && !(m_MsgParam.dwStyle & MB_NORESOURCE))
{
TCHAR tchText [_MAX_PATH];
int nCount = ::LoadString(m_MsgParam.hInstanceStrings, (UINT)lpszText, tchText, _MAX_PATH);
if (nCount)
sText = (CPPString)tchText;
} //if
}
else
{
//lpszText is a pointer to the button text
sText = (CPPString)lpszText;
} //if
*/ } //if
} //if
//Try to get a button text from resources
if (sText.IsEmpty() && (NULL != m_MsgParam.hInstanceStrings) && !(m_MsgParam.dwStyle & MB_NORESOURCE) && dwResID)
{
TCHAR tchText [_MAX_PATH];
int nCount = ::LoadString(m_MsgParam.hInstanceStrings, dwResID, tchText, _MAX_PATH);
if (nCount)
sText = (CPPString)tchText;
} //if
if (sText.IsEmpty())
sText = sDefText;
return sText;
} //End of GetLocalizedButtonText
void CPPMessageBoxTemplate::RemoveAllButtons()
{
//ENG: Removes an existing control buttons
//RUS: ������� ������������ ������ ����������
for (UINT i = 0; i < m_vecButtons.size(); ++i)
{
STRUCT_BUTTONS & sb = m_vecButtons [i];
if (NULL != sb.hWnd)
{
::DestroyWindow(sb.hWnd);
sb.hWnd = NULL;
}
} //for
m_vecButtons.clear();
//ENG: Removes a checkbox
//RUS: ������� checkbox
if (NULL != m_stCheckBtn.hWnd)
{
::DestroyWindow(m_stCheckBtn.hWnd);
m_stCheckBtn.hWnd = NULL;
} //if
//ENG: Removes a text of the checkbox
//RUS: ������� ����� checkbox
if (NULL != m_stCheckText.hWnd)
{
::DestroyWindow(m_stCheckText.hWnd);
m_stCheckText.hWnd = NULL;
} //if
}
SIZE CPPMessageBoxTemplate::PrepareMessageBox(HWND hwnd)
{
RemoveAllButtons();
//ENG: Gets a device context
//RUS: �������� �������� ����������
HDC hDC = ::GetDC(NULL);
HFONT hOldFont = (HFONT)::SelectObject(hDC, m_hFont);
SIZE sz = {0, 0};
SIZE szTemp = {0, 0};
//---------------- Header area -----------------------
m_dwHeaderHeight = 0;
if (m_MsgParam.nHeaderHeight)
{
//ENG: Stores a minimal height of the header area
//RUS: ��������� ����������� ������ ������� ���������
m_dwHeaderHeight = m_MsgParam.nHeaderHeight;
szTemp.cx = 0;
m_sHeader = GetString(m_MsgParam.lpszHeaderText);
if (!m_sHeader.IsEmpty())
{
//ENG: If header text is available then prepare him to output
//RUS: ���� ����� ��������� ����������, �� �������������� ��� � ������
m_pHeader.PrepareOutput(hDC, m_sHeader, &szTemp);
szTemp.cx += m_dwSizes[PPMSGBOX_SIZE_MSGX] * 2;
//ENG: Updates a height of the header area
//RUS: ��������� ������ ������� ���������
m_dwHeaderHeight = max(m_dwHeaderHeight, szTemp.cy + m_dwSizes[PPMSGBOX_SIZE_MSGX] * 2);
} //if
sz.cx = max(sz.cx, szTemp.cx);
//ENG: Header separator will be drawn
//RUS: ����������� ��������� ����� �������
m_sHeaderSepText = GetString(m_MsgParam.pHeaderBk.lpszSepText);
if (m_MsgParam.pHeaderBk.nSepType != PPMSGBOX_SEP_NONE)
{
::GetTextExtentPoint32(hDC, m_sHeaderSepText, m_sHeaderSepText.GetLength(), &szTemp);
sz.cx = max(sz.cx, (int)(szTemp.cx + 2 * m_dwSizes [PPMSGBOX_SIZE_SEPX]));
} //if
} //if
sz.cy += m_dwHeaderHeight;
//--------------- Message area -----------------------
m_dwMessageHeight = 0;
if (!m_sText.IsEmpty())
{
//ENG: If message text is available then prepare him to output
//RUS: ���� ����� ��������� ����������, �� �������������� ��� � ������
m_pDrawer.PrepareOutput(hDC, m_sText, &szTemp);
//ENG: Updates a height of the message area
//RUS: ��������� ������ ������� ���������
m_dwMessageHeight = szTemp.cy + 2 * m_dwSizes [PPMSGBOX_SIZE_MSGY];
sz.cx = max(sz.cx, (int)(szTemp.cx + 2 * m_dwSizes [PPMSGBOX_SIZE_MSGX]));
} //if
sz.cy += m_dwMessageHeight;
//--------------- Moreinfo area -----------------------
m_dwMoreInfoHeight = 0;
CPPString sMoreInfo = GetString(m_MsgParam.lpszMoreInfo);
if (!sMoreInfo.IsEmpty())
{
//ENG: If message text is available then prepare him to output
//RUS: ���� ����� ��������� ����������, �� �������������� ��� � ������
m_pMoreInfo.PrepareOutput(hDC, sMoreInfo, &szTemp);
//ENG: Updates a height of the message area
//RUS: ��������� ������ ������� ���������
m_dwMoreInfoHeight = szTemp.cy + 2 * m_dwSizes [PPMSGBOX_SIZE_MSGY];
sz.cx = max(sz.cx, (int)(szTemp.cx + 2 * m_dwSizes [PPMSGBOX_SIZE_MSGX]));
} //if
//---------------- Control area ----------------------
m_dwControlHeight = m_dwSizes [PPMSGBOX_SIZE_CTRLY];
if ((m_MsgParam.pControlBk.nEffectBk >= 0) || (m_MsgParam.pControlBk.nSepType != PPMSGBOX_SEP_NONE))
{
m_dwControlHeight += m_dwSizes [PPMSGBOX_SIZE_CTRLY];
//ENG: Comtrol separator will be drawn
//RUS: ����������� ������� ���������� ����� �������
m_sControlSepText = GetString(m_MsgParam.pControlBk.lpszSepText);
if (m_MsgParam.pControlBk.nSepType != PPMSGBOX_SEP_NONE)
{
::GetTextExtentPoint32(hDC, m_sControlSepText, m_sControlSepText.GetLength(), &szTemp);
sz.cx = max(sz.cx, (int)(szTemp.cx + 2 * m_dwSizes [PPMSGBOX_SIZE_SEPX]));
} //if
} //if
//ENG: Get a checkbox type
//RUS: �������� ��� checkbox
m_stCheckBtn.hWnd = NULL;
m_stCheckBtn.nTypeBtn = (m_MsgParam.dwStyle & MB_CHECKBOX);
m_stCheckText = m_stCheckBtn;
if (m_stCheckBtn.nTypeBtn)
{
//ENG: Checkbox will drawn
//RUS: ������ ����������� � �������
m_dwControlHeight += m_dwSizes [PPMSGBOX_SIZE_CTRLY] + m_dwSizes [PPMSGBOX_SIZE_CHKY];
//ENG: Gets the sizes of the text of the checkbox
//RUS: �������� ������� ������ ������
CPPString sCheckBoxText = GetString(m_MsgParam.lpszCheckBoxText);
if (sCheckBoxText.IsEmpty())
sCheckBoxText = _T("Do not show again");
CPPString str = GetLocalizedButtonText(MB_CHECKBOX, sCheckBoxText);
::GetTextExtentPoint32(hDC, str, str.GetLength(), &szTemp);
//ENG: Check a max width of the dialog
//RUS: ��������� ������������ ������ �������
sz.cx = max(sz.cx, (int)(szTemp.cx + 2 * m_dwSizes [PPMSGBOX_SIZE_CHKX] + 20));
m_stCheckBtn.hWnd = ::CreateWindow(_T("BUTTON"), NULL /*sCheckText*/,
WS_VISIBLE | WS_CHILD | WS_TABSTOP | BS_AUTOCHECKBOX,
0, 0, m_dwSizes [PPMSGBOX_SIZE_CHKY], // + m_dwSizes [PPMSGBOX_SIZE_CHKY] / 2 + sz.cx,
m_dwSizes [PPMSGBOX_SIZE_CHKY], hwnd, NULL, NULL, NULL);
if (m_MsgParam.dwStyle & MB_CHECKBOXCHECKED)
::SendMessage(m_stCheckBtn.hWnd, BM_SETCHECK, (WPARAM)BST_CHECKED, FALSE);
//ENG: To the transparency output of the text of the checkbox
//RUS: ����� ��� checkbox ������� �������� ��� ����������� ������
m_stCheckText.hWnd = ::CreateWindow(_T("STATIC"), str,
WS_VISIBLE | WS_CHILD | SS_LEFT,
0, 0, szTemp.cx, m_dwSizes [PPMSGBOX_SIZE_CHKY],
hwnd, NULL, NULL, NULL);
::SendMessage(m_stCheckText.hWnd, WM_SETFONT, (WPARAM)m_hFont, FALSE);
} //if
//ENG: Creates a list of the buttons
//RUS: ������� ������ ������
STRUCT_BUTTONS sb;
sb.hWnd = NULL;
CPPString sCustomButtons = GetString(m_MsgParam.lpszCustomButtons);
if (((m_MsgParam.dwStyle & MB_TYPEMASK) == MB_OK) && sCustomButtons.IsEmpty())
m_bIsCancelExist = TRUE;
else
m_bIsCancelExist = FALSE;
//ENG: Try to load a custom buttons
//RUS: ������� ��������� ���������������� ������
if (!sCustomButtons.IsEmpty())
{
//ENG: Will be use the custom buttons
//RUS: ����� ������������ ���������������� ������
sCustomButtons.Remove(_T('\r'));
DWORD dwButton = IDCUSTOM1;
sCustomButtons += _T("\n");
int nLength = sCustomButtons.GetLength();
for (int i = 0; (i < nLength) && (dwButton <= IDCUSTOM4); ++i)
{
int nIndex = sCustomButtons.Find(_T('\n'), i);
if (i != nIndex)
{
//ENG: A custom button was found
//RUS: ���������������� ������ �������
// SetButtonText(dwButton, m_MsgParam.sCustomButtons.Mid(i, nIndex - i));
sb.nTypeBtn = dwButton;
m_vecButtons.push_back(sb);
dwButton ++;
i = nIndex;
} //if
} //for
} //if
if (0 == m_vecButtons.size())
{
//ENG: Custom buttons not used
//RUS: ���������������� ������ �� ������������
switch (m_MsgParam.dwStyle & MB_TYPEMASK)
{
case MB_OK:
sb.nTypeBtn = IDOK;
m_vecButtons.push_back(sb);
break;
case MB_OKCANCEL:
sb.nTypeBtn = IDOK;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDCANCEL;
m_vecButtons.push_back(sb);
m_bIsCancelExist = TRUE;
break;
case MB_RETRYCANCEL:
sb.nTypeBtn = IDRETRY;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDCANCEL;
m_vecButtons.push_back(sb);
m_bIsCancelExist = TRUE;
break;
case MB_YESNO:
sb.nTypeBtn = IDYES;
m_vecButtons.push_back(sb);
if (m_MsgParam.dwStyle & MB_YESTOALL)
{
sb.nTypeBtn = IDYESTOALL;
m_vecButtons.push_back(sb);
} //if
sb.nTypeBtn = IDNO;
m_vecButtons.push_back(sb);
if (m_MsgParam.dwStyle & MB_NOTOALL)
{
sb.nTypeBtn = IDNOTOALL;
m_vecButtons.push_back(sb);
} //if
break;
case MB_CONTINUEABORT:
sb.nTypeBtn = IDCONTINUE;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDABORT;
m_vecButtons.push_back(sb);
break;
case MB_YESNOCANCEL:
sb.nTypeBtn = IDYES;
m_vecButtons.push_back(sb);
if (m_MsgParam.dwStyle & MB_YESTOALL)
{
sb.nTypeBtn = IDYESTOALL;
m_vecButtons.push_back(sb);
} //if
sb.nTypeBtn = IDNO;
m_vecButtons.push_back(sb);
if (m_MsgParam.dwStyle & MB_NOTOALL)
{
sb.nTypeBtn = IDNOTOALL;
m_vecButtons.push_back(sb);
} //if
sb.nTypeBtn = IDCANCEL;
m_vecButtons.push_back(sb);
m_bIsCancelExist = TRUE;
break;
case MB_ABORTRETRYIGNORE:
sb.nTypeBtn = IDABORT;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDRETRY;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDIGNORE;
m_vecButtons.push_back(sb);
break;
case MB_CANCELTRYCONTINUE:
sb.nTypeBtn = IDCANCEL;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDRETRY;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDCONTINUE;
m_vecButtons.push_back(sb);
m_bIsCancelExist = TRUE;
break;
case MB_SKIPSKIPALLCANCEL:
sb.nTypeBtn = IDSKIP;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDSKIPALL;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDCANCEL;
m_vecButtons.push_back(sb);
m_bIsCancelExist = TRUE;
break;
case MB_IGNOREIGNOREALLCANCEL:
sb.nTypeBtn = IDIGNORE;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDIGNOREALL;
m_vecButtons.push_back(sb);
sb.nTypeBtn = IDCANCEL;
m_vecButtons.push_back(sb);
m_bIsCancelExist = TRUE;
break;
} //switch
} //if
//ENG: Adds a Help button to the message box.
//RUS: ��������� ������ Help
if (m_MsgParam.dwStyle & MB_HELP)
{
sb.nTypeBtn = IDHELP;
m_vecButtons.push_back(sb);
} //if
//ENG: Adds a Report button to the message box.
//RUS: ��������� ������ Report
if (m_MsgParam.dwReportMsgID && (NULL != m_MsgParam.hParentWnd))
{
sb.nTypeBtn = IDREPORT;
m_vecButtons.push_back(sb);
} //if
//ENG: Adds a More Info button to message box.
//RUS: ��������� ������ "�������������"
m_sMoreInfoSepText = GetString(m_MsgParam.pMoreInfoBk.lpszSepText);
m_sMoreInfoClosed = m_sMoreInfoOpened = _T("");
if (!sMoreInfo.IsEmpty())
{
sb.nTypeBtn = IDMOREINFO_CLOSED;
m_vecButtons.push_back(sb);
//Load a "MoreInfo" button text
m_sMoreInfoOpened = GetLocalizedButtonText(IDMOREINFO_OPENED);
m_sMoreInfoClosed = GetLocalizedButtonText(IDMOREINFO_CLOSED);
} //if
//ENG: Remembers a default button
//RUS: ���������� ������ �� ���������
m_nDefBtn = (m_MsgParam.dwStyle >> 8) & 0x0f;
if (m_nDefBtn >= m_vecButtons.size())
m_nDefBtn = 0;
//ENG:
m_dwSizes [PPMSGBOX_SIZE_BTNY] = 0;
m_dwSizes [PPMSGBOX_SIZE_BTNX] = 0;
int nCustomIndex = 0;
for (UINT i = 0; i < m_vecButtons.size(); ++i)
{
STRUCT_BUTTONS & sbTemp = m_vecButtons [i];
CPPString sBtnText;
if (IDMOREINFO_CLOSED == sbTemp.nTypeBtn)
{
::GetTextExtentPoint32(hDC, m_sMoreInfoOpened, m_sMoreInfoOpened.GetLength(), &szTemp);
SIZE szTemp2;
::GetTextExtentPoint32(hDC, m_sMoreInfoClosed, m_sMoreInfoClosed.GetLength(), &szTemp2);
szTemp.cx = max (szTemp.cx, szTemp2.cx);
szTemp.cy = max (szTemp.cy, szTemp2.cy);
sBtnText = m_sMoreInfoClosed;
}
else
{
if ((sbTemp.nTypeBtn >= IDCUSTOM1) && (sbTemp.nTypeBtn <= IDCUSTOM4))
{
int nIndex = sCustomButtons.Find(_T('\n'), nCustomIndex);
sBtnText = sCustomButtons.Mid(nCustomIndex, nIndex - nCustomIndex);
nCustomIndex = nIndex + 1;
}
else
sBtnText = GetLocalizedButtonText(sbTemp.nTypeBtn);
::GetTextExtentPoint32(hDC, sBtnText, sBtnText.GetLength(), &szTemp);
} //if
szTemp.cx = ::MulDiv(szTemp.cx, 80, 45);//40);
szTemp.cy = ::MulDiv(szTemp.cy, 23, 13);
m_dwSizes [PPMSGBOX_SIZE_BTNY] = max ((DWORD)szTemp.cy, m_dwSizes [PPMSGBOX_SIZE_BTNY]);
m_dwSizes [PPMSGBOX_SIZE_BTNX] = max ((DWORD)szTemp.cx, m_dwSizes [PPMSGBOX_SIZE_BTNX]);
//ENG: Common styles for all buttons
//RUS: ����� ����� ��� ���� ������
DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP;
if (sbTemp.nTypeBtn == IDHELP)
{
//RUS: ���������� ������������ ������ Help, ��� ��� ��� �� ������ ������� �����������
if (i != m_nDefBtn)
dwStyle |= BS_PUSHBUTTON;
else
{
dwStyle |= BS_DEFPUSHBUTTON;
m_sTimeoutText = sBtnText;
if ((m_MsgParam.nTimeoutSeconds > 0) || ((m_MsgParam.nDisabledSeconds > 0) && !m_MsgParam.bDisableAllCtrls))
sBtnText.Format(PPMSGBOX_BUTTON_DISABLED, m_sTimeoutText, m_dwCountdownTimer);
} //if
}
else
{
if ((m_MsgParam.nDisabledSeconds > 0) && m_MsgParam.bDisableAllCtrls)
{
dwStyle |= WS_DISABLED | BS_PUSHBUTTON;
}
else
{
if (i != m_nDefBtn)
{
dwStyle |= BS_PUSHBUTTON;
}
else
{
m_sTimeoutText = sBtnText;
if (m_MsgParam.nDisabledSeconds > 0)
dwStyle |= BS_PUSHBUTTON;
else
dwStyle |= BS_DEFPUSHBUTTON;
if (m_dwCountdownTimer > 0)
{
sBtnText.Format(PPMSGBOX_BUTTON_DISABLED, m_sTimeoutText, m_dwCountdownTimer);
if (m_MsgParam.nDisabledSeconds > 0)
dwStyle |= WS_DISABLED;
} //if
} //if
} //if
} //if
//ENG: Create a button
//RUS: ������� ������
sbTemp.hWnd = ::CreateWindow(_T("BUTTON"), sBtnText, dwStyle, 0, 0, 0, 0, hwnd, (HMENU)sbTemp.nTypeBtn, NULL, NULL);
::SendMessage(sbTemp.hWnd, WM_SETFONT, (WPARAM)m_hFont, FALSE);
//ENG: Set a focus for default button
//RUS: ��� ������ �� ���������, �������� �� �����
if (i == m_nDefBtn)
::SetFocus(sbTemp.hWnd);
} //if
if (m_dwSizes [PPMSGBOX_SIZE_BTNX] < 80)
m_dwSizes [PPMSGBOX_SIZE_BTNX] = 80;
if (m_dwSizes [PPMSGBOX_SIZE_BTNY] < 23)
m_dwSizes [PPMSGBOX_SIZE_BTNY] = 23;
//ENG: Calculates a width of the all buttons area
//RUS: ������������ ������ ������� ���� ������
szTemp.cx = m_dwSizes [PPMSGBOX_SIZE_CTRLX] + m_vecButtons.size() * (m_dwSizes [PPMSGBOX_SIZE_CTRLX] + m_dwSizes [PPMSGBOX_SIZE_BTNX]);
sz.cx = max(sz.cx, szTemp.cx);
m_dwControlHeight += m_dwSizes [PPMSGBOX_SIZE_BTNY];
//ENG: Add a height of the control area
//RUS: ��������� ������ ������� ���������
sz.cy += m_dwControlHeight;
//----------------------------------------------------
//ENG: Add the edges and the caption
//RUS: ��������� ������ � ��������� �������
sz.cx += 2 * ::GetSystemMetrics(SM_CXFIXEDFRAME);
sz.cy += ::GetSystemMetrics(SM_CYCAPTION) + 2 * ::GetSystemMetrics(SM_CYFIXEDFRAME);
//ENG: Release a device context
//RUS: ����������� �������� ���������
::SelectObject(hDC, hOldFont);
if (NULL != hDC)
::ReleaseDC(NULL, hDC);
return sz;
} //End of GetClientSize
void CPPMessageBoxTemplate::DrawBox(HWND hwnd, HDC hDC)
{
BOOL bAutoReleaseDC = FALSE;
if (NULL == hDC)
{
hDC = ::GetDC(hwnd);
bAutoReleaseDC = TRUE;
} //if
RECT rcClient;
::GetClientRect(hwnd, &rcClient);
RECT rcFull = rcClient;
if (!m_bMoreInfoOpened)
rcFull.bottom += m_dwMoreInfoHeight;
int nWidth = rcFull.right - rcFull.left;
int nHeight = rcFull.bottom - rcFull.top;
HDC hMemDC = ::CreateCompatibleDC(hDC);
HDC hSrcDC = ::CreateCompatibleDC(hDC);
HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, nWidth, nHeight);
HBITMAP hOldSrcBitmap = NULL;
HFONT hOldFont = NULL;
if (NULL == m_hBitmapBk)
{
hOldFont = (HFONT)::SelectObject(hSrcDC, m_hFont);
m_hBitmapBk = ::CreateCompatibleBitmap(hDC, nWidth, nHeight);
hOldSrcBitmap = (HBITMAP)::SelectObject(hSrcDC, m_hBitmapBk);
RECT rect = rcClient;
//Fill a message box window
if (m_MsgParam.pMsgBoxBk.nEffectBk >= 0)
m_pDrawer.GetDrawManager()->FillEffect(hSrcDC, m_MsgParam.pMsgBoxBk.nEffectBk, &rcFull, m_MsgParam.pMsgBoxBk.crStartBk, m_MsgParam.pMsgBoxBk.crMidBk, m_MsgParam.pMsgBoxBk.crEndBk);
else
{
HBRUSH hBrush = ::CreateSolidBrush(::GetSysColor(COLOR_3DFACE));
::FillRect(hSrcDC, &rcFull, hBrush);
::DeleteObject(hBrush);
} //if
//Draw a header area
if (0 != m_dwHeaderHeight)
{
//Fill a header background
rcClient.bottom = rcClient.top + m_dwHeaderHeight;
if (m_MsgParam.pHeaderBk.nEffectBk >= 0)
m_pDrawer.GetDrawManager()->FillEffect(hSrcDC, m_MsgParam.pHeaderBk.nEffectBk, &rcClient, m_MsgParam.pHeaderBk.crStartBk, m_MsgParam.pHeaderBk.crMidBk, m_MsgParam.pHeaderBk.crEndBk);
//Draw a Separator
rcClient.top = rcClient.bottom;
if (m_MsgParam.pHeaderBk.nSepType != PPMSGBOX_SEP_NONE)
DrawSeparator(hSrcDC, &rcClient, m_MsgParam.pHeaderBk.nSepType, m_sHeaderSepText, m_MsgParam.pHeaderBk.nSepAlign);
} //if
rcClient.top += m_dwMessageHeight;
//Draw a control area
if (m_MsgParam.pControlBk.nEffectBk >= 0)
{
rcClient.bottom = rcClient.top + m_dwControlHeight;
m_pDrawer.GetDrawManager()->FillEffect(hSrcDC, m_MsgParam.pControlBk.nEffectBk, &rcClient, m_MsgParam.pControlBk.crStartBk, m_MsgParam.pControlBk.crMidBk, m_MsgParam.pControlBk.crEndBk);
} //if
if (m_MsgParam.pControlBk.nSepType != PPMSGBOX_SEP_NONE)
DrawSeparator(hSrcDC, &rcClient, m_MsgParam.pControlBk.nSepType, m_sControlSepText, m_MsgParam.pControlBk.nSepAlign);
//Draw a MoreInfo area background
if (m_dwMoreInfoHeight)
{
rcClient.top += m_dwControlHeight;
//Draw a control's area
if (m_MsgParam.pMoreInfoBk.nEffectBk >= 0)
{
rcClient.bottom = rcFull.bottom;
m_pDrawer.GetDrawManager()->FillEffect(hSrcDC, m_MsgParam.pMoreInfoBk.nEffectBk, &rcClient, m_MsgParam.pMoreInfoBk.crStartBk, m_MsgParam.pMoreInfoBk.crMidBk, m_MsgParam.pMoreInfoBk.crEndBk);
} //if
if (m_MsgParam.pMoreInfoBk.nSepType != PPMSGBOX_SEP_NONE)
DrawSeparator(hSrcDC, &rcClient, m_MsgParam.pMoreInfoBk.nSepType, m_sMoreInfoSepText, m_MsgParam.pMoreInfoBk.nSepAlign);
} //if
::SelectObject(hSrcDC, hOldFont);
rcClient = rect;
}
else
{
hOldSrcBitmap = (HBITMAP)::SelectObject(hSrcDC, m_hBitmapBk);
} //if
hOldFont = (HFONT)::SelectObject(hMemDC, m_hFont);
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap);
::BitBlt(hMemDC, 0, 0, nWidth, nHeight, hSrcDC, 0, 0, SRCCOPY);
//Draw a header's area
if (0 != m_dwHeaderHeight)
{
//Fill a header background
rcClient.bottom = rcClient.top + m_dwHeaderHeight;
//Draw a header text
if (!m_sHeader.IsEmpty())
{
RECT rcHeader;
rcHeader.left = rcClient.left + m_dwSizes[PPMSGBOX_SIZE_MSGX];
rcHeader.right = rcClient.right - m_dwSizes[PPMSGBOX_SIZE_MSGX];
rcHeader.top = rcClient.top + m_dwSizes[PPMSGBOX_SIZE_MSGY];
rcHeader.bottom = rcClient.bottom - m_dwSizes[PPMSGBOX_SIZE_MSGY];
m_pHeader.DrawPreparedOutput(hMemDC, &rcHeader);
} //if
//Draw a Separator
rcClient.top = rcClient.bottom;
} //if
//Draw a message's area
if (!m_sText.IsEmpty())
{
//Margins from the top
RECT rcMsg = rcClient;
rcMsg.bottom = rcClient.top + m_dwMessageHeight - m_dwSizes [PPMSGBOX_SIZE_MSGY];
rcMsg.top += m_dwSizes [PPMSGBOX_SIZE_MSGY];
rcMsg.left += m_dwSizes [PPMSGBOX_SIZE_MSGX];
rcMsg.right -= m_dwSizes [PPMSGBOX_SIZE_MSGX];
m_pDrawer.DrawPreparedOutput(hMemDC, &rcMsg);
} //if
//Draw a moreinfo's area
if (m_bMoreInfoOpened && m_dwMoreInfoHeight)
{
//Margins from the top
RECT rcMoreInfo = rcFull;
rcMoreInfo.top += rcMoreInfo.bottom - m_dwMoreInfoHeight + m_dwSizes [PPMSGBOX_SIZE_MSGY];
rcMoreInfo.left += m_dwSizes [PPMSGBOX_SIZE_MSGX];
rcMoreInfo.right -= m_dwSizes [PPMSGBOX_SIZE_MSGX];
m_pMoreInfo.DrawPreparedOutput(hMemDC, &rcMoreInfo);
} //if
::SelectObject(hMemDC, hOldFont);
if (!bAutoReleaseDC)
::BitBlt(hDC, 0, 0, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
else
{
::BitBlt(hDC, 0, 0, nWidth, m_dwHeaderHeight + m_dwMessageHeight, hMemDC, 0, 0, SRCCOPY);
if (m_bMoreInfoOpened)
::BitBlt(hDC, 0, rcFull.bottom - m_dwMoreInfoHeight, nWidth, m_dwMoreInfoHeight, hMemDC, 0, nHeight - m_dwMoreInfoHeight, SRCCOPY);
}
::SelectObject(hMemDC, hOldBitmap);
::SelectObject(hSrcDC, hOldSrcBitmap);
::DeleteObject(hBitmap);
::DeleteDC(hMemDC);
::DeleteDC(hSrcDC);
if (bAutoReleaseDC)
::ReleaseDC(hwnd, hDC);
} //End of DrawBox
void CPPMessageBoxTemplate::DrawSeparator(HDC hDC, LPCRECT lpRect, int nTypeSeparator, LPCTSTR lpszText, int nTextAlign)
{
RECT rect = {lpRect->left + m_dwSizes [PPMSGBOX_SIZE_SEPX], lpRect->top, lpRect->right - m_dwSizes [PPMSGBOX_SIZE_SEPX], lpRect->bottom};
RECT rcTemp = rect;
if ((NULL != lpszText) && (0 != lpszText [0]))
{
CPPString sText = lpszText;
SIZE sz = {0, 0};
::GetTextExtentPoint32(hDC, lpszText, sText.GetLength(), &sz);
rcTemp.top = rect.top - sz.cy / 2;
rcTemp.bottom = rcTemp.top + sz.cy;
switch (nTextAlign)
{
case PPMSGBOX_ALIGN_LEFT:
::DrawState(hDC, NULL, NULL, (LPARAM)lpszText, 0, rcTemp.left, rcTemp.top, 0, 0, DST_TEXT | DSS_DISABLED);
rcTemp.left += sz.cx + m_dwSizes [PPMSGBOX_SIZE_SEPX];
break;
case PPMSGBOX_ALIGN_RIGHT:
::DrawState(hDC, NULL, NULL, (LPARAM)lpszText, 0, rcTemp.right - sz.cx, rcTemp.top, 0, 0, DST_TEXT | DSS_DISABLED);
rcTemp.right -= sz.cx + m_dwSizes [PPMSGBOX_SIZE_SEPX];
break;
case PPMSGBOX_ALIGN_CENTER:
rcTemp.right = rcTemp.left + (rcTemp.right - rcTemp.left - sz.cx) / 2;
::DrawState(hDC, NULL, NULL, (LPARAM)lpszText, 0, rcTemp.right, rcTemp.top, 0, 0, DST_TEXT | DSS_DISABLED);
rcTemp.right -= m_dwSizes [PPMSGBOX_SIZE_SEPX];
if (rcTemp.left < rcTemp.right)
{
rcTemp.top = rcTemp.bottom = rect.top;
switch (nTypeSeparator)
{
case PPMSGBOX_SEP_ETCHED:
::DrawEdge(hDC, &rcTemp, EDGE_ETCHED, BF_TOP);
break;
case PPMSGBOX_SEP_BLACK:
m_pDrawer.GetDrawManager()->DrawLine(hDC, rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.top, RGB (0, 0, 0));
break;
case PPMSGBOX_SEP_WHITE:
m_pDrawer.GetDrawManager()->DrawLine(hDC, rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.top, RGB (255, 255, 255));
break;
} //switch
} //if
rcTemp.left = rcTemp.right + 2 * m_dwSizes [PPMSGBOX_SIZE_SEPX] + sz.cx;
rcTemp.right = rect.right;
break;
} //switch
rcTemp.top = rcTemp.bottom = rect.top;
} //if
if (rcTemp.left < rcTemp.right)
{
switch (nTypeSeparator)
{
case PPMSGBOX_SEP_ETCHED:
::DrawEdge(hDC, &rcTemp, EDGE_ETCHED, BF_TOP);
break;
case PPMSGBOX_SEP_BLACK:
m_pDrawer.GetDrawManager()->DrawLine(hDC, rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.top, RGB (0, 0, 0));
break;
case PPMSGBOX_SEP_WHITE:
m_pDrawer.GetDrawManager()->DrawLine(hDC, rcTemp.left, rcTemp.top, rcTemp.right, rcTemp.top, RGB (255, 255, 255));
break;
} //switch
} //if
} //End of DrawSeparator