I first wrote the STATUS sample in C using the messages provided by the Win32 API. I decided to create a multiple-part status bar to show these elements:
Normal text
Text that pops out
Text without a border
An owner-drawn section with a bitmap displayed
The following code, found in the STATUS.C file on the companion disc, creates the status bar and breaks it into parts. The array of integers passed in the SB_SETPARTS message (or the MFC SetParts member function) is an array of endpoints for each part of the status bar. Because I take care of sizing my status bar when I handle the WM_SIZE message, I fill in the actual endpoints at that time. As is the case for most of the common controls, you need to include the COMMCTRL.H header file in order to use status bars in your application, and you must include the COMCTL32.LIB file in your list of libraries.
static HWND hWndStatus;
static int aWidths [4];
switch (message)
{
case WM_CREATE:
hWndStatus = CreateWindowEx (
0L, // extended style
STATUSCLASSNAME, // create status bar
"", // window title
WS_CHILD | WS_BORDER |
WS_VISIBLE | SBS_SIZEGRIP, // window styles
0, 0, 0, 0, // x, y, width, height
hWnd, // parent window
(HMENU)ID_STATUSBAR, // ID
hInst, // instance
NULL); // window data
if (hWndStatus == NULL)
MessageBox (NULL, "Status Bar not created!", NULL,
MB_OK);
// Break the status bar into four parts.
SendMessage (hWndStatus, SB_SETPARTS, 4, (LPARAM)aWidths);
Now that you've created the status bar, you should give it some text to display. What good is a status bar that doesn't say anything? Setting text is as easy as sending a message (or calling an MFC member function). The trick to displaying the different kinds of text shown in Figure 1-1 on page 9 is to set the drawing style when setting the text. The wParam parameter for the SB_SETTEXT message is a combination of the (zero-based) part of the status bar that receives the text and the text drawing style.
// Set the text in the first part to normal.
SendMessage (hWndStatus, SB_SETTEXT, 0,
(LPARAM)"Mouse position:");
// Set the text in the second part to pop out.
SendMessage (hWndStatus, SB_SETTEXT, 1 | SBT_POPOUT,
(LPARAM)"This text pops out.");
// Set the text in the third part to have no borders.
SendMessage (hWndStatus, SB_SETTEXT, 2 | SBT_NOBORDERS,
(LPARAM)"This text has no borders.");
// Load the bitmap for the owner-drawn part of the status bar.
hBmp = LoadBitmap (hInst, MAKEINTRESOURCE (ID_BITMAP));
// Set the fourth part to be owner-drawn and pass the bitmap.
SendMessage (hWndStatus, SB_SETTEXT, 3 | SBT_OWNERDRAW,
(LPARAM)hBmp);
The MFC version of the code (the MFCSTATUS sample) creates the status bar in the view class of the OnCreate handler in the MFCSTVW.CPP file. The status bar is created and the text and parts initially set using the member functions provided by the CStatusBarCtrl class. As you can see, the code is very similar. One difference is in the SetText member function. Whereas the SB_SETTEXT message packed both the part and the drawing style into wParam, the SetText member function receives these two values separately: first the part and then the drawing style. Another difference between the C version and the MFC version is that you must include the AFXCMN.H file, which defines the new common control classes, in your STDAFX.H file.
// The view class is defined as follows in MFCSTVW.H.
class CMfcstatusView : public CView
{
protected: // create from serialization only
CMfcstatusView ();
DECLARE_DYNCREATE (CMfcstatusView);
CStatus m_Status;
// Attributes
public:
CMfcstatusDoc *GetDocument ();
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides.
// {{AFX_VIRTUAL (CMfcstatusView)
public:
virtual void OnDraw (CDC *pDC); // overridden to draw
// this view
protected:
// }}AFX_VIRTUAL
// Implementation
public:
virtual ~CMfcstatusView ();
#ifdef _DEBUG
virtual void AssertValid () const;
virtual void Dump (CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
// {{AFX_MSG (CMfcstatusView)
afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct);
afx_msg void OnSimple ();
afx_msg void OnMultiple ();
afx_msg void OnSize (UINT nType, int cx, int cy);
afx_msg void OnMouseMove (UINT nFlags, CPoint point);
// }}AFX_MSG
DECLARE_MESSAGE_MAP ()
};
// The status bar is created in MFCSTVW.CPP.
int CMfcstatusView::OnCreate (LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate (lpCreateStruct) == -1)
return -1;
// Create the status bar.
m_Status.Create (WS_CHILD | WS_BORDER | WS_VISIBLE |
SBARS_SIZEGRIP,
Crect (0, 0, 0, 0),
this,
ID_STATUSBAR);
int aWidths [4] = {0, 0, 0, 0};
// Set the status bar to have four parts.
m_Status.SetParts (4, aWidths);
// Set the text in the first part to normal.
m_Status.SetText ((LPCTSTR)"Mouse position:", 0, 0);
// Set the text in the second part to pop out.
m_Status.SetText ((LPCTSTR)"This text pops out.", 1,
SBT_POPOUT);
// Set the text in the third part to have no borders.
m_Status.SetText ((LPCTSTR)"This text has no borders.",
2,
SBT_NOBORDERS);
// Set the fourth part to be owner-drawn.
m_Status.SetText ((LPCTSTR)"", 3, SBT_OWNERDRAW);
return 0;
}
Sizing the status bar window and its parts isn't difficult. It's simply a matter of handling the WM_SIZE message, moving the status bar window, and setting the endpoints for the parts in the status bar. Following is the C code I used; I leave the MFC code as an exercise for you.
case WM_SIZE:
// Resize the status bar to fit along the bottom of the client
area.
MoveWindow (hWndStatus, 0, HIWORD(lParam) - 10, LOWORD(lParam),
HIWORD(lParam), TRUE);
// Set the rectangles for the multiple parts of the status bar.
// Make each part 1/4 of the width of the client area.
aWidths [0] = LOWORD(lParam) / 4;
aWidths [1] = LOWORD(lParam) / 2;
aWidths [2] = LOWORD(lParam) - aWidths [0];
aWidths [3] = -1;
SendMessage (hWndStatus, SB_SETPARTS, 4, (LPARAM)aWidths);
break;