Adding a clock to the status bar

Here is how to add the current time to your status bar...

Step 1:

Derive a CMyStatusBar class from CStatusBar as follows:
//MyStatusBar.h:
//==============
class CMyStatusBar : public CStatusBar {
     DECLARE_DYNCREATE(CMyStatusBar)
public:
     CMyStatusBar();
     ~CMyStatusBar();
private:
     CString m_strClockFormat;
public:
     void SetClockFormat(LPCTSTR strClockFormat);
     // Overrides
     // ClassWizard generated virtual function overrides
     //{{AFX_VIRTUAL(CMyStatusBar)
     //}}AFX_VIRTUAL
     // Generated message map functions
     //{{AFX_MSG(CMyStatusBar)
     afx_msg void OnDestroy();
     afx_msg void OnUpdateIndicatorTime(CCmdUI* pCmdUI);
     afx_msg int OnCreate( LPCREATESTRUCT lpCreateStruct );
     //}}AFX_MSG
     DECLARE_MESSAGE_MAP()
};


/////////////////////////////////////////////////////////////////
//MyStatusBar.cpp:
//==============
#include "stdafx.h"
#include "MyStatusBar.h"
#include "Resource.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

IMPLEMENT_DYNCREATE(CMyStatusBar, CStatusBar)

BEGIN_MESSAGE_MAP(CMyStatusBar, CStatusBar)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_UPDATE_COMMAND_UI(ID_INDICATOR_TIME, OnUpdateIndicatorTime)
END_MESSAGE_MAP()

CMyStatusBar::CMyStatusBar()
: CStatusBar()
, m_strClockFormat("%H:%M:%S")
{
}

CMyStatusBar::~CMyStatusBar() {
}

void CMyStatusBar::SetClockFormat(LPCTSTR strClockFormat) {
     m_strClockFormat = strClockFormat;
}

int CMyStatusBar::OnCreate(LPCREATESTRUCT lpCreateStruct) {
     // make sure time gets updated every second, even when idle
     CStatusBar::OnCreate(lpCreateStruct);
     SetTimer(ID_INDICATOR_TIME,1000,NULL);
     return 0;
}

void CMyStatusBar::OnUpdateIndicatorTime(CCmdUI* pCmdUI) {
     pCmdUI->Enable(true);
     pCmdUI->SetText(CTime::GetCurrentTime().Format(m_strClockFormat));
}

void CMyStatusBar::OnDestroy() {
     KillTimer(ID_INDICATOR_TIME);
     ProgressDestroy();
     CStatusBar::OnDestroy();
}

Step 2:

Create a new indicator pane by first adding a new menu called "ID_INDICATOR", add a single dropdown called "Indicator", add a single item to the menu called "Time" - This should create a menu item with id ID_INDICATOR_TIME. Give it a prompt string of, say, "HH:MM:SS" which reserves an approriate amount of space for the pane. NOTE: If you change time format by calling SetClockFormat you will need to ensure that your ID_INDICATOR_TIME pane is big enough.

Step 3:

Add a new indicator pane called ID_INDICATOR_TIME to your list of indicator in your mainframe eg. this is my indicator list...
static const UINT indicators[] = {
     ID_SEPARATOR,           // status line indicator
     ID_INDICATOR_CAPS,
     ID_INDICATOR_NUM,
     ID_INDICATOR_SCRL,
     ID_INDICATOR_TIME,  // <-- new indicator pane
};

Step 4:

Replace all existing uses of CStatusBar in your app with CMyStatusBar - in particular, the member variable in your mainframe m_wndStatusBar;



Comments

  • Time is not accurate

    Posted by Legacy on 08/10/2002 12:00am

    Originally posted by: Amir

    Has anyone noticed that the time is not very accurate. I use the SetTimer() method with a value of 1000 and the timer always runs faster than the actual time. Is there a more accurate way to keep time?

    -Amir

    Reply
  • SetTextAlign

    Posted by Legacy on 04/29/2002 12:00am

    Originally posted by: ray

    How could I apply SetTextAlign function in StatusBar ?
    

    Reply
  • Adding a clock to the status bar in A Dialog Box

    Posted by Legacy on 12/06/2001 12:00am

    Originally posted by: Dhayalan

    The Following part of the Code Wil be Used to Create a Status bar in Dialog box and Update the Panes of the Status Bar. Normally The Status bar will be attached to a CMainFrame object and we need to Send a ON_UPDATE_COMMAND_UI message to update the Controls.
    Since it is a DialogBased Appliation we don't have CMainFrame, we have to send the message direly to the Pane.

    This is a Simple Application with four pane with Date and Time.

    Step 0:
    --------
    Declare these Variables in the .h file
    CStatusBar m_StatBar;

    step1 :
    -------
    Add the Pane Indicators in the Resource file and add strings for the Coressponding Id's

    In MyDialog.cpp


    static UINT indicators[]={
    ID_INDICATOR_TESTING,
    ID_INDICATOR_TEST_PROG,
    ID_INDICATOR_DATE,
    ID_INDICATOR_TIME
    };

    Step2:
    -----
    Add these Message handler Manualy and By using Clwizard

    BEGIN_MESSAGE_MAP(CCheckDlg, CDialog)
    //{{AFX_MSG_MAP(CCheckTIDlg)
    ON_WM_TIMER()
    ON_WM_CREATE()
    //}}AFX_MSG_MAP
    ON_UPDATE_COMMAND_UIID_INDICATOR_TIME,OnUpdateTimer)
    END_MESSAGE_MAP()


    step3:
    ------
    Add this Code in to the Corrosponding Functions

    int CCheckDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if (CDialog::OnCreate(lpCreateStruct) == -1)
    return -1;

    CRect rect;
    this->GetWindowRect(&rect);
    rect.top = rect.bottom- 25;

    m_StatBar.GetStatusBarCtrl().Create(WS_CHILD | WS_BORDER | WS_VISIBLE|SBARS_SIZEGRIP|CCS_BOTTOM ,rect,this,
    IDC_MY_SATUSBAR);
    m_StatBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT));

    m_StatBar.SetPaneInfo(0,ID_INDICATOR_TESTING,SBPS_NORMAL ,60);
    m_StatBar.SetPaneInfo(1,ID_INDICATOR_TEST_PROG,SBPS_NORMAL ,170);
    m_StatBar.SetPaneInfo(2,ID_INDICATOR_DATE,SBPS_NORMAL,50);
    m_StatBar.SetPaneInfo(3,ID_INDICATOR_TIME,SBPS_STRETCH,60);

    SetTimer(1,100,NULL);
    return 0;

    }

    void CCheckDlg::OnTimer(UINT nIDEvent)
    {

    har tmpbuf[50];
    _strdate(tmpbuf);
    m_StatBar.SetPaneText(2,tmpbuf,TRUE);

    CTime theTime=CTime::GetCurrentTime();
    CString szTime;
    szTime=theTime.Format(" %I:%M:%S");
    m_StatBar.SetPaneText(3,szTime,TRUE);
    CDialog::OnTimer(nIDEvent);
    }
    Reg,
    Dhayalan.V

    Reply
  • I use this code...(for MFC Dialogs !!)

    Posted by Legacy on 06/09/2001 12:00am

    Originally posted by: Sebastian

    ...your idea is not very successful!
    
    My Code uses the Class Item WM_TIMER added from the Class Assistent

    /// starts here ///
    void Arbeiten::OnTimer(UINT nIDEvent)
    {
    CString csUhr;
    switch ( nIDEvent )
    {
    case 0x3B0 :
    COleDateTime dZeit = COleDateTime::GetCurrentTime();

    csUhr.Format ("%02d.%02d.%02d", dZeit.GetHour(), dZeit.GetMinute(), dZeit.GetSecond() );
    GetDlgItem(IDC_uhr)->SetWindowText(csUhr);

    break;
    }
    CPropertyPage::OnTimer(nIDEvent);
    }
    /// My program uses CPropertyPage ;-P
    /// end

    Reply
  • Problems in NT

    Posted by Legacy on 02/03/2000 12:00am

    Originally posted by: Miguel Angel

    I have tried to use your code in Windows NT, but in the CMainFrame::OnCreate(), in the portion of code:
    if (!m_wndStatusBar.Create(this) ||
    !m_wndStatusBar.SetIndicators(indicators,
    sizeof(indicators)/sizeof(UINT)))
    {
    TRACE0("Failed to create status bar\n");
    return -1; // fail to create
    }

    The call to SetIndicators returns a 0. Any idea about the solution?
    I had no trouble in Windows 95/98.

    Best regards,
    Miguel Angel

    Reply
  • Dangerous situation

    Posted by Legacy on 03/04/1999 12:00am

    Originally posted by: Tom Bech

    1. By the way, this identical method are presented on MSDN KB Q99198. There are also method with global timer.
    2. When I implemented this method I have got serious problem: my time didn't work when I opened child window (time didn't appear). When I closed child window time appear.
    Reason: I like order, so I added ID_INDICATOR_TIME in string table just after ID_INDICATOR_REC and it has number up one to the previous.
    There was no warning from Visual Studio. But this number corresponds to
    ID_INDICATOR_KANA which has own implementation UI in CFrameWnd.
    My timer worked (when was no child window) because my implementation
    of time UI hides standard implementation of ID_INDICATOR_KANA
    (in class CMainFrame). But in class CChildFrame there was no my
    implementation and after opening child window my time works as
    ID_INDICATOR_KANA (by the way, what is it: 'kana'?!?).
    Solution: Set unique value for ID_INDICATOR_TIME.
    (and don't like order when you work with MFC)

    (sorry for my 'english')

    Reply
  • Ever-living timer

    Posted by Legacy on 02/12/1999 12:00am

    Originally posted by: Alex Rogovtsev

    One way to keep timer alive is to use an application-defined TimerProc callback function
    
    SetTimer(0x1000, 1000, TimerProc)
    instead of installing WM_TIMER message in application's message queue
    SetTimer(0x1000, 1000, NULL)

    So you should do only a few step to keep timer alive:
    (Let's do this for a simple SDI application)

    Step 1:
    Insert in your CMainFrame::OnCreate() function only one statement
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
    if (!m_wndStatusBar.Create(this) ||
    !m_wndStatusBar.SetIndicators(indicators,
    sizeof(indicators)/sizeof(UINT)))
    return -1; // fail to create
    m_wndStatusBar.SetTimer(0x1000, 1000, TimerProc); //<-- new statement
    return 0;
    }

    Step 2:
    Add application defined function TimerProc() to your CMainFrame.cpp file
    void CALLBACK EXPORT TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
    {
    CCmdUI cui;
    CMainFrame *pMainWnd = (CMainFrame *)AfxGetMainWnd(); //this is for SDI project
    cui.m_nID = ID_INDICATOR_TIME;
    cui.m_nIndex = pMainWnd->m_wndStatusBar.CommandToIndex(ID_INDICATOR_TIME);
    cui.m_pMenu = NULL;
    cui.m_pOther = &pMainWnd->m_wndStatusBar;
    pMainWnd->OnUpdateTime(&cui);
    }

    Step 3:
    Add ON_UPDATE_COMMAND message handler to CMainFrame message map
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    ON_UPDATE_COMMAND_UI(ID_INDICATOR_TIME, OnUpdateTime)
    //{{AFX_MSG_MAP(CMainFrame)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    // DO NOT EDIT what you see in these blocks of generated code !
    ON_WM_CREATE()
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    add OnUpdateTime() function to CMainFrame class

    void CMainFrame::OnUpdateTime(CCmdUI* pCmdUI)
    {
    // Get current date and format it
    CTime time = CTime::GetCurrentTime();
    CString strTime = time.Format(_T("%X"));
    m_wndStatusBar.SetPaneText(m_wndStatusBar.CommandToIndex(ID_INDICATOR_TIME),strTime);
    pCmdUI->Enable(TRUE);

    }

    Step 4:
    Add a new indicator pane called ID_INDICATOR_TIME to your list of indicator in your CMainFrame indicator list.

    static const UINT indicators[] = {
    ID_SEPARATOR, // status line indicator
    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_INDICATOR_SCRL,
    ID_INDICATOR_TIME, // <-- new indicator pane
    };
    Step 4:
    Add a new string with ID_INDICATOR_TIME to a string table and set its caption to "00:00:00"
    Step 5:
    Remove m_wndStatusBar from protected section in CMainFrame.h and add it to public section

    Remove afx_msg void OnUpdateTime(CCmdUI* pCmdUI) function from protected message map and add it to public section

    public:
    afx_msg void OnUpdateTime(CCmdUI* pCmdUI);
    // Generated message map functions
    protected:
    //{{AFX_MSG(CMainFrame)
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    // NOTE - the ClassWizard will add and remove member functions here.
    // DO NOT EDIT what you see in these blocks of generated code!
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()

    That's all - your timer will live forever!

    This is a sample project that illustrate this method Timer.zip


    Reply
  • Timer is frozen.

    Posted by Legacy on 11/27/1998 12:00am

    Originally posted by: L. Chang

    Because WM_TIMER is a low-priority message, if the program is doing a
    
    time-consuming work and displays the progress at the same time, the
    timer on the status bar is frozen. Any method to keep the timer "alive"?

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • A modern mobile IT strategy is no longer an option, it is an absolute business necessity. Today's most productive employees are not tied to a desk, an office, or a location. They are mobile. And your company's IT strategy has to be ready to support them with easy, reliable, 24/7 access to the business information they need, from anywhere in the world, across a broad range of communication devices. Here's how some of the nation's most progressive corporations are meeting the many needs of their mobile workers …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds