📄 ngmessagebox.cpp
字号:
// Getting the base dialog unit used in pixel <-> d.u. conversion
CRect rc( 0, 0, CX_DLGUNIT_BASE, CY_DLGUNIT_BASE );
MapDialogRect( rc );
m_dimDlgUnit = rc.Size();
// Creating the nested controls
CreateRtfCtrl();
CreateIcon();
CreateBtns();
// Updating the layout - preparing to show
UpdateLayout();
// Disabling the ESC key
if( m_uEscCmdId == (UINT)IDC_STATIC )
ModifyStyle( WS_SYSMENU, NULL );
// Focusing and setting the defaul button
if( m_uDefCmdId != (UINT)IDC_STATIC )
{
GetDlgItem( m_uDefCmdId )->SetFocus();
SetDefID( m_uDefCmdId );
return FALSE;
}
return TRUE;
}
BOOL CNGMessageBox::OnWndMsg( UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult )
{
if( message == WM_NOTIFY )
{
REQRESIZE* prr = (REQRESIZE*)lParam;
if( prr->nmhdr.code == EN_REQUESTRESIZE )
{
// (1)
// The rich edit control requested a resize.
// Store the requested resize.
m_dimMsg.cx = prr->rc.right - prr->rc.left;
m_dimMsg.cy = prr->rc.bottom - prr->rc.top;
*pResult = NULL;
return TRUE;
}
}
else if( message == WM_CLOSE )
{
if( m_uEscCmdId != (UINT)IDC_STATIC )
EndDialog( m_uEscCmdId );
return TRUE;
}
return CDialog::OnWndMsg( message, wParam, lParam, pResult );
}
BOOL CNGMessageBox::OnCmdMsg( UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo )
{
if (nCode == CN_COMMAND)
{
if ( pHandlerInfo == NULL && nID != (WORD)IDC_STATIC )
{
EndDialog( nID );
return TRUE;
}
}
return CDialog::OnCmdMsg( nID, nCode, pExtra, pHandlerInfo );
}
BOOL CNGMessageBox::PreTranslateMessage( MSG* pMsg )
{
if( pMsg->message == WM_KEYDOWN )
{
if( pMsg->wParam == VK_RETURN )
{
CWnd* pWnd = GetFocus();
if( pWnd != NULL )
{
UINT uIDC = (UINT)pWnd->GetDlgCtrlID();
for( int i = 0; i < m_aBtns.GetSize(); ++i )
if( m_aBtns[i].uIDC == uIDC )
{
m_uDefCmdId = uIDC;
break;
}
}
EndDialog( m_uDefCmdId );
return TRUE;
}
else if( pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_CANCEL )
{
if( m_uEscCmdId != (UINT)IDC_STATIC )
EndDialog( m_uEscCmdId );
return TRUE;
}
}
return CDialog::PreTranslateMessage( pMsg );
}
/////////////////////////////////////////////////////////////////////////////
// CNGMessageBox - Overrides
void CNGMessageBox::CreateRtfCtrl()
{
// Creating the Rich Edit control
CRect rcDummy; // dimesion doesn't matter here
m_edCtrl.Create( WS_CHILD|WS_VISIBLE|ES_LEFT|ES_MULTILINE|ES_READONLY,
rcDummy, this, (UINT)IDC_STATIC );
m_edCtrl.SetBackgroundColor( FALSE, ::GetSysColor( COLOR_3DFACE ) );
m_edCtrl.SetFont( GetFont() );
if( m_bRtf )
{
// Loading a RTF message
EDITSTREAM es;
es.dwCookie = (DWORD)(LPCTSTR)m_strMsg;
es.dwError = 0;
es.pfnCallback = _LoadRtfCallback;
m_edCtrl.StreamIn( SF_RTF, es );
}
else
{
// Loading a plain text message
m_edCtrl.SetWindowText( m_strMsg );
}
/////////////////////////////////////////////////////////
// Calculating the best Rich Edit control dimension
//
// Note:
// There's no Rich Edit operation to get the minimum
// width it needs to show its contents without line
// breaks. However, given a width, we can check
// how much height it needs to show its text (see
// bottomless rich edit controls).
// We'll this mechanism to perform a binary search
// and find that best width value.
m_edCtrl.SetEventMask( ENM_REQUESTRESIZE );
m_dimMsg.cx = 0;
m_dimMsg.cy = 0;
// Performing a binary search for the best dimension
int cxFirst = 0;
int cxLast = ::GetSystemMetrics( SM_CXFULLSCREEN );
int cyMax = 0;
do
{
// taking a guess
int cx = ( cxFirst + cxLast ) / 2;
// testing it
CRect rc( 0, 0, cx, 1 );
m_edCtrl.MoveWindow( rc );
m_edCtrl.SetRect( rc );
m_edCtrl.RequestResize();
// if it's the first guess, take it anyway
if( cyMax == 0 )
cyMax = m_dimMsg.cy;
// refining the guess
if( m_dimMsg.cy > cyMax )
{
cxFirst = cx + 1;
}
else
{
cxLast = cx - 1;
}
}
while( cxFirst < cxLast );
}
void CNGMessageBox::CreateBtns()
{
// The minimum button's dimension
m_dimBtn = CSize( FromDlgX( m_aMetrics[CX_MIN_BTN] ), 0 );
// DC and Font for use in some dimension calculations
CClientDC dc( this );
CFont* pWndFont = GetFont();
dc.SelectObject( pWndFont );
CRect rcDummy; // dimesion doesn't matter here
int cBtns = m_aBtns.GetSize();
for( int i = 0; i < cBtns; ++i )
{
BTNDATA& btndata = m_aBtns[i];
// Finding the minimum dimension needed to
// properly show any button
CSize dimBtn = dc.GetTextExtent( btndata.strBtn );
m_dimBtn.cx = max( m_dimBtn.cx, dimBtn.cx );
m_dimBtn.cy = max( m_dimBtn.cy, dimBtn.cy );
// Creating the button with MFC's CButton help.
CButton btnCtrl;
btnCtrl.Create( btndata.strBtn,
WS_CHILD|WS_VISIBLE|WS_TABSTOP,
rcDummy, this, btndata.uIDC );
btnCtrl.SetFont( pWndFont );
btnCtrl.UnsubclassWindow();
}
// Add the button margins
m_dimBtn.cx += 2 * FromDlgX( m_aMetrics[CX_BTN_BORDER] );
m_dimBtn.cy += 2 * FromDlgY( m_aMetrics[CY_BTN_BORDER] );
}
void CNGMessageBox::CreateIcon()
{
if( m_hIcon != NULL )
{
CRect rcDummy; // dimesion doesn't matter here
// Creating the icon control
m_stIconCtrl.Create( NULL, WS_CHILD|WS_VISIBLE|WS_DISABLED|SS_ICON, rcDummy, this );
m_stIconCtrl.SetIcon( m_hIcon );
}
}
// Converts d.u. in pixel (x axe)
int CNGMessageBox::FromDlgX( int x )
{ return x * m_dimDlgUnit.cx / CX_DLGUNIT_BASE; }
// Converts d.u. in pixel (y axe)
int CNGMessageBox::FromDlgY( int y )
{ return y * m_dimDlgUnit.cy / CY_DLGUNIT_BASE; }
// Updates the layout
void CNGMessageBox::UpdateLayout()
{
// Caching the borders
int cxLeft = FromDlgX( m_aMetrics[CX_LEFT_BORDER] );
int cxRight = FromDlgX( m_aMetrics[CX_RIGHT_BORDER] );
int cyTop = FromDlgY( m_aMetrics[CY_TOP_BORDER] );
int cyBottom = FromDlgY( m_aMetrics[CY_BOTTOM_BORDER] );
// Caching the space between buttons
int cxBtnsSpace = FromDlgX( m_aMetrics[CX_BTNS_SPACE] );
// The minimum dimensios of the client area
// (starting with the message)
CSize dimClient = m_dimMsg;
int xMsg = 0;
if( m_hIcon != NULL )
{
// Adding the icon
xMsg = m_dimIcon.cx + FromDlgX( m_aMetrics[CX_ICON_MSG_SPACE] );
dimClient.cx += xMsg;
if( dimClient.cy < m_dimIcon.cy )
dimClient.cy = m_dimIcon.cy;
}
xMsg += cxLeft;
// Caching the minimum width needed for all buttons
int cBtns = m_aBtns.GetSize();
int cxBtns =
( cBtns - 1 ) * FromDlgX( m_aMetrics[CX_BTNS_SPACE] ) +
cBtns * m_dimBtn.cx;
if( dimClient.cx < cxBtns )
dimClient.cx = cxBtns;
dimClient.cx += cxLeft + cxRight;
dimClient.cy += cyTop + cyBottom + m_dimBtn.cy + FromDlgY( m_aMetrics[CY_BTNS_MSG_SPACE] );
// Set client dimensions
CRect rc( 0, 0, dimClient.cx, dimClient.cy );
CalcWindowRect( rc );
MoveWindow( rc );
CenterWindow();
// Icon layout
if( m_hIcon != NULL )
m_stIconCtrl.MoveWindow( cxLeft, cyTop, m_dimIcon.cx, m_dimIcon.cy );
// Message layout
m_dimMsg.cx += 2;
xMsg = ( xMsg + dimClient.cx - cxRight - m_dimMsg.cx ) / 2;
m_edCtrl.MoveWindow( xMsg, cyTop, m_dimMsg.cx, m_dimMsg.cy );
// Buttons layout
int x = ( dimClient.cx - cxBtns ) / 2;
int y = dimClient.cy - cyBottom - m_dimBtn.cy;
for( int i = 0; i < cBtns; ++i )
{
CWnd* pWndCtrl = GetDlgItem( m_aBtns[i].uIDC );
pWndCtrl->MoveWindow( x, y, m_dimBtn.cx, m_dimBtn.cy );
x += m_dimBtn.cx + cxBtnsSpace;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -