MFC allows you to easily add status bars to CFrameWnd-derived windows.
However, if you want to add a status bar to a dialog, you’re going to find the
going just a bit more difficult.
Basically, it turned out that I had to dig very deep into the MFC documentation
in order to find anything to help me out. One example I found is by ZEKSER
Cyril. His techniques works fine, but (IMHO) is not very "clean"
since you have to place an invisible static object on the dialog as a kind of
placeholder for the status bar. However, I do want to thank him very much for
showing me the light at the end of the tunnel.
The technique I came up with works like this: First, you need to develop your
dialog (and define its CDialog-based class). Nothing new here so far.
Then, insert the following code into the CDialog::OnInitDialog function
(the m_StatBar variable is of type CStatusBarCtrl).
BOOL CMyDlg::OnInitDialog() { CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon /************************************************************************/ /* Adding STATUSBAR */ /************************************************************************/ int nTotWide; // total width of status bar CRect rect; this->GetWindowRect(&rect); rect.top = rect.bottom- 25; m_bRvStatOk = m_StatBar.Create(WS_CHILD | WS_BORDER | WS_VISIBLE ,rect,this, IDC_STATUSBAR); if (m_bRvStatOk == NULL) { AfxMessageBox ("Status Bar not created!", NULL, MB_OK ); } // // get size of window, use to configure the status // bar with four separate parts // CRect rWin; this->GetWindowRect(&rWin); nTotWide = rWin.right-rWin.left; // // Make each part 1/4 of the total width of the window. // m_Widths[0] = nTotWide / 4; m_Widths[1] = nTotWide / 2; m_Widths[2] = nTotWide - m_Widths[0]; m_Widths[3] = -1; m_StatBar.SetMinHeight(25); m_StatBar.SetParts( 4, m_Widths); // // now lets put some text, different styles into parts of status bar // m_StatBar.SetText("WITH BORDER.", 0,0); m_StatBar.SetText("WITHOUT BORDER.",1,SBT_NOBORDERS); m_StatBar.SetText("POPUP.",2,SBT_POPOUT); // // make the last part owner-drawn, add a bitmap // m_StatBar.SetText(NULL,3, SBT_OWNERDRAW); // hBmp is a Global Variable of type HBITMAP hBmp = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1)); /************************************************************************/ /* End STATUSBAR */ /************************************************************************/ // TODO: Add extra initialization here return TRUE; // return TRUE unless you set the focus to a control }
The fourth pane of the status bar is owner drawn because it is used to display
a bitmap. In order to do this, simply add a message handler for the dialog’s
WM_DRAWITEM message. Once you’ve added that function, update it so that when finished
it looks like the following.
void CMyDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { // // Draw bitmap in status bar // HDC hdcMem; // device context for memory HGDIOBJ hbmOld; // old bitmap area we're over-writing BITMAP bm; // bitmap we're using // // Create a compatible DC in memory // hdcMem = CreateCompatibleDC(lpDrawItemStruct->hDC); // Select the "logo.bmp" bitmap into the DC. hbmOld = ::SelectObject(hdcMem, hBmp); // Get the size of the bitmap ::GetObject(hBmp, sizeof(bm), &bm); // Blt the bitmap to the part. BitBlt(lpDrawItemStruct->hDC,lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0,SRCCOPY); // // Add some text..1st. get bounding rectangle, then position & display text // char szText[16]; RECT rText; // text rectangle rText.left = lpDrawItemStruct->rcItem.left+24; rText.top = lpDrawItemStruct->rcItem.top; rText.right = lpDrawItemStruct->rcItem.right-20; rText.bottom = lpDrawItemStruct->rcItem.bottom; // // add some text after the logo bitmap here // memset(szText,0,sizeof(szText)); strcpy(szText,"LOGO"); // text to draw SelectObject( lpDrawItemStruct->hDC, GetStockObject( ANSI_VAR_FONT ) ); ::SetBkColor(lpDrawItemStruct->hDC, 0x00c0c0c0); // set background color ExtTextOut(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.left+24, lpDrawItemStruct->rcItem.top+4, ETO_OPAQUE, &rText, szText, strlen(szText),NULL ); // draw the text in the rectangle rText // // End adding text. Reselect the original object into the DC. // SelectObject(hdcMem, hbmOld); // Delete the compatible DC. DeleteDC(hdcMem); }
Make the following changes to the dialog’s header file.
CStatusBarCtrl m_StatBar; ..................................... ................................... ...................................... }class CMyDlg : public CDialog { // Construction public: CMyDlg(CWnd* pParent = NULL); // standard constructor
Finally, make the following changes to the resource.h file.
//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // #define IDM_ABOUTBOX 0x0010 #define IDC_STATUSBAR 32500 ..................................... ................................... ......................................
That’s it! You now have a status bar at the bottom of your dialog!