In a previous article I showed how to make AfxMessageBox to display a message box with auto-close, by using a CBT hook.
One reader suggested that whould be nice if the message box displays also the time left until auto-closing. I thought that’s a very good idea and promissed an update. Here it is!
Of course, may be more than one solution. I chose one which appends “Time left: xxx sec.” in the bottom of the built-in static text control. For this purpose, I added two private methods to CAutoMessageBox class:
- CAutoMessageBox::_InitStaticTextCtrl – initializes the static contol: finds the static control, keeps in mind the initial text, makes space for an extra-line of text, and assigns an ID to be used later.
void CAutoMessageBox::_InitStaticTextCtrl() { // search for static text control CWnd* pWndCtrl = GetWindow(GW_CHILD); while(NULL != pWndCtrl->GetSafeHwnd()) { const int nMaxCount = 63; CString strClass; ::GetClassName(pWndCtrl->m_hWnd, strClass.GetBufferSetLength(nMaxCount), nMaxCount); DWORD dwStyle = pWndCtrl->GetStyle(); strClass.ReleaseBuffer(); if(!strClass.CompareNoCase(_T("STATIC")) && !(dwStyle & SS_ICON)) { // set static control ID ::SetWindowLong(pWndCtrl->m_hWnd, GWL_ID, IDC_STATIC_TEXT); // keep in mind the initial text pWndCtrl->GetWindowText(m_strIntitalText); // calculate extra-line height and width CClientDC dc(this); CFont* pFont = pWndCtrl->GetFont(); ASSERT(NULL != pFont); CFont* pOldFont = dc.SelectObject(pFont); CRect rcText(0, 0, 0, 0); dc.DrawText(CString(_T("Time left: 999 sec.")), rcText, DT_SINGLELINE|DT_CALCRECT); dc.SelectObject(pOldFont); // add extra-line space CRect rcCtrl; pWndCtrl->GetWindowRect(rcCtrl); ScreenToClient(rcCtrl); rcCtrl.bottom += rcText.Height(); const int nExtraWidth = rcText.Width() - rcCtrl.Width(); if(nExtraWidth > 0) rcCtrl.right += nExtraWidth; pWndCtrl->MoveWindow(rcCtrl); break; } // get next child control pWndCtrl = pWndCtrl->GetWindow(GW_HWNDNEXT); } }
- CAutoMessageBox::_SetStaticTextCtrl – sets the text which contains time left.
void CAutoMessageBox::_SetStaticTextCtrl() { UINT nRemained = (m_nTimeOut - m_nElapsed) / 1000 + 1; CWnd* pWndStatic = GetDlgItem(IDC_STATIC_TEXT); ASSERT(NULL != pWndStatic->GetSafeHwnd()); CString strText; strText.Format(_T("%s\nTime left: %u sec."), m_strIntitalText, nRemained); pWndStatic->SetWindowText(strText); }
For more implementation details of CAutoMessageBox class, download and have a look in the attached demo project.
See also
- Codexpert blog: AfxMessageBox with Auto-close (Part 1)