Status bar – let’s display the timestamp there. We need to get the timestamp from the document so we add one public function there (after the GetGame). Open SudokuDoc.h and append a new line:
The view is notified when information is changed so we can use the handler (OnUpdate) to also handle this information. If one looks in the code in the CMainFrame class then one sees that the statusbar is a child of that window, nothing to do with the view – so we will delegate the actual display of information to the frame window itself.
In the SudokuView.cpp file modify it to be as follows (adding the #include “MainFrm.h” after the existing #include “SudokuView.h”)
Next we modify the OnUpdate function, adding a new line directly after the case statement
case CSudokuDoc::eLoadGame: //Update the status bar on the frame static_cast<CMainFrame*>(GetParentFrame())->DisplayStatusInfo(GetDocument()->GetInfo());
The GetParentFrame returns a generic CFrameWnd pointer, we cast this to our specific CMainFrame class which is a derived class from CFrameWnd. Notice this has a new function – DisplayStatusInfo – which we must now add to the CMainFrame class. Modify the MainFrm.h file so it is as follows:
The program should compile but the status bar needs a little work now. In the OnCreate function of the CMainFrame there should be the following 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 }
This creates a default status bar. We want a custom one which will display menu prompts as the default one does and also have two panes, one for the hint (later article) and one for the time stamp.
We also want some extra functionality so we will create a class derived from CStatusBar (NOT CStatusBarCtrl – careful when selecting the base class). I have explained in step 3 how to create a CGridButton – we will do similar to create a CSudokuStatusBar.
You should have the following:
class CSudokuStatusBar : public CStatusBar{ DECLARE_DYNAMIC(CSudokuStatusBar)public: CSudokuStatusBar(); virtual ~CSudokuStatusBar();protected: DECLARE_MESSAGE_MAP()};
In the header file for the CMainFrame we need to add a #include “SudokuStatusBar” after the #pragma once and change the CStatusBar m_wndStatusBar into CSudokuStatusBar.
protected: // control bar embedded members CSudokuStatusBar m_wndStatusBar; CToolBar m_wndToolBar;
In the OnCreate of the CMainFrame we need to make a change:
This:
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 }
We need to pass the string information, passing it by reference (&) means that it is not constantly being copied into a new CString variable - efficiency.
We have created our own statusbar to encapsulate the updating of the display elements. Should we decide to add an extra pane to the status bar or to rearrange the layout in future then we don’t need to change a lot of code in other classes. Note we even use a #define for the different pane indexes – to rearrange the layout is then just changing a #define value.
Conclusion:
Here we customised the default MFC status bar to provide visual feedback for the user.
Previous article in the series is here: Sudoku in MFC: Part 3
There we loaded and saved data to file on the hard disc. We also investigated the interaction between the document and view based classes in the application architecture.
Next article in the series is here: Sudoku in MFC: Part 5
Here we will be providing keyboard support (in PreTranslateMessage) to navigate the grid in response to arrow keys, we will also be entering numbers into the grid cells from the keyboard.
Two points to bear in mind.
You may use the code but you are not allowed to distribute the resulting application either for free or for a reward (monetary or otherwise). At least not without my express permission.
I will perform some things to demonstrate a point – it is not to be taken as that meaning it is a ‘best’ practice, in fact an alternative might be simpler and suitable. Some points in the code would even be called poor design and a possible source of errors.
Comments (0)