AfxMessageBox with Auto-close – Part 2

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!

AfxMessageBox with Auto-close
AfxMessageBox with Auto-close

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

Downloads

4 thoughts on “AfxMessageBox with Auto-close – Part 2”

  1. Is there a way to handle the messagebox buttons size ? I mean, what if I want to modify “Ok” button text, with “Go to next file” button text …

    Reply
  2. Here is code that stretch ABORT button, for ex.

    LRESULT CAutoMessageBox::OnInitDialog(WPARAM wParam, LPARAM lParam)
    {

    if(m_nTimeOut > 0)
    {
    _InitStaticTextCtrl();
    SetTimer(0, m_nTimerStep, NULL);
    }
    if(m_bShowProgress)
    {
    VERIFY(_AddProgressCtrl());
    // m_progress.SetRange(0, m_nTimeOut);
    m_progress.SetRange32(0, m_nTimeOut); // use 32-bit limit for a larger range
    m_progress.SetPos(m_nElapsed);
    }

    CButton* pAbort = (CButton*)GetDlgItem(IDABORT);
    if(pAbort)
    {
    CRect rect;
    pAbort->GetWindowRect(&rect);
    ScreenToClient(&rect);
    rect.OffsetRect(CPoint(-20, 0));
    rect.right += 20;
    pAbort->MoveWindow(rect);
    }

    return TRUE;
    }

    Reply
  3. I still have a question: I don’t know why doesn’t work MB_DEFBUTTON2 or MB_DEFBUTTON3 style flags on CAutoMessageBox … as long I didn’t use CAutoMessageBox on demo project, everything is all right.

    Reply

Leave a Comment