Lab 8.4: Adding a Pane to the Status Bar
Estimated time to complete this lab: 45 minutes
To complete the exercises in this lab, you must have the required software. For detailed information about the labs and setup for the labs, see Labs in this course.
Objectives
After completing this lab, you will be able to:
® Add a pane to a status bar.
® Provide a handler to update the displayed text.
Prerequisites
There are no prerequisites for this lab.
Exercise
The following exercise provides practice with the concepts and techniques covered in this chapter:
® Exercise 1: Implementing a Time Pane
In this exercise, you will add a new pane to the status bar and set its text to the current time. You will also add a command handler to provide updates to the status bar.
Create a simple SDI application saved as TimeStamp.
In this exercise, you will add a new pane to the status bar and set its text to the current time. Use an UPDATE_COMMAND_UI handler to provide updates to the status bar.
CStatusBar includes support for adding panes to the status bar. The framework stores pane identifier information in an array with the leftmost pane at position 0 in the array. When you create a status bar, you use an array of pane IDs that the framework associates with the corresponding panes. You can then either use the pane ID or the array index to access a pane.
By default, the first pane is "elastic": It takes up the status bar length not used by the other panes, so that the other panes are right-aligned.
If you examine CMainFrame::On Create, you can find the creation code for the status bar:
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
In the code above, CStatusBar::SetIndicators uses the strings associated with the pane IDs in the indicators array to size and initialize the text that appears in the panes. To add a pane, you must create a new identifier for the pane and then add the identifier for it to the indicator array.
Add a pane to the status bar
Every status-bar pane is associated with an ID. To create an ID for the new pane, you will add a new ID using a dummy menu. A dummy menu is a menu resource that is used to store IDs that are used in your application, but that are not directly used by a menu. Another reason for using a dummy menu for creating an ID is that ClassWizard can be used to add handlers for the ID.
1. In ResourceView, right-click the menu resource and insert a new menu.
2. Right-click the new top-level menu item and select Properties. Select the Keep Visible button (pushpin) in the Properties dialog box to keep the dialog box on top. Enter "DummyMenu" for the caption string.
3. Click on the new drop-down menu item to select it. Set the ID of the menu to ID_INDICATOR_TIME. Set the caption to some value that will remind you what the ID is for, such as ID INDICATOR PANE.
4. Set the prompt value to HH:MM AM. This value will determine the size of the pane as well as its initial value.
5. Open MainFrm.cpp.
6. Add ID_INDICATOR_TIME to the indicators array. Save MainFrm.cpp. The array follows:
static UINT indicators[] =
{
ID_SEPARATOR, // status line indicator
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
ID_INDICATOR_TIME,
};
Update the time pane
Whenever the framework finishes processing all the pending messages for the MainFrame window, it sends itself a WM_IDLEUPDATECMDUI message. This message is one of the generators of the UPDATE_COMMAND_UI message that is sent by the system to CCmdTarget-derived objects such as CStatusBar. Use this message to force the update of the time pane.
1. Click ClassWizard on the View menu, or press CTRL+W. If a dialog box appears asking if you want to add a new class, click Cancel.
2. Click the Message Maps tab and select CMainFrame as the class name. In the Object IDs list box, select the new message identifier, ID_INDICATOR_TIME. Select UPDATE_COMMAND_UI as the message and add a function for this message. ClassWizard will prompt you for the function name. Rename the function to OnUpdateTime.
3. Click Edit Code. ClassWizard will place you in the body of the new handler. Code the OnUpdateTime function by creating a CTime object and initializing it to the current system time as follows:
CTime time = CTime::GetCurrentTime();
4. Use CTime::Format to format the time in HH:MM AM format and assign that string to a new CString.
CString sTime = time.Format ("%I:%M %p");
5. Set the text of the pane to the time:
pCmdUI->SetText(sTime);
6. Save MainFrm.cpp. The complete function follows:
void CMainFrame::OnUpdateTime(CCmdUI *pCmdUI)
{
CTime time = CTime::GetCurrentTime();
CString sTime = time.Format ("%I:%M %p");
// Now set the text of the pane.
pCmdUI->SetText(sTime);
}
7. Build and run the TimeStamp application. You will see the current time displayed in the fifth pane of the status bar as shown in the following illustration:
Use a timer to cause background updating
The TimeStamp application will show the time and update itself as long as there are messages for its frame window to process. However, TimeStamp is little more than a clock in a status bar. Without messages, a WM_IDLEUPDATECMDUI message is not sent to update the time pane. In this section, you can set up a timer for TimeStamp to process and update time.
1. Open MainFrm.cpp. At the end of the OnCreate function and before the return statement, set a timer that will send a message once a second. The ID of this timer is irrelevant and can therefore be any value; there is no callback function.
SetTimer(1234,1000, NULL);
2. Click ClassWizard on the View menu, or press CTRL+W.
3. In the CMainFrame class, add a function for WM_TIMER. Even though you cannot add functionality to the default behavior, you must map the message through a function for the message pump to empty the queue and send the UPDATE_COMMAND_UI message. You can leave the OnTimer handler as provided or you can comment out the call to the default function.
4. Save MainFrm.cpp. Build and run TimeStamp.exe. You will notice that the timer pane updates properly whether or not TimeStamp.exe is in the foreground or background and whether or not there has been activity in the window.
The completed code for this exercise is in \Labs\Ch08\Lab04\Ex01
Comments
Post a Comment