StatusBar on Dialogs

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.


class CMyDlg : public CDialog
{

// Construction
public:
	CMyDlg(CWnd* pParent = NULL);	// standard constructor
	CStatusBarCtrl	m_StatBar;

	.....................................
	...................................
	......................................
}
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!



Comments

  • how i can add progress bar on the status bar?

    Posted by Legacy on 01/27/2004 12:00am

    Originally posted by: shalu

    I have to add a progress bar on the status bar. My application is dialog based, so i used your code for adding the status bar on my application, but now i have to add progress bar also.

    Reply
  • how to update the text in the pane

    Posted by Legacy on 10/28/2003 12:00am

    Originally posted by: naresh

    can u just help me in how to update the text in the status bar cntrl pane

    Reply
  • Code compiles but OnDrawItem not being called

    Posted by Legacy on 07/28/2003 12:00am

    Originally posted by: John Dillon

    I'm trying to add a right-aligned LED into a CStatusBarCtrl and am using this code. Everything compiles fine except that the OnDrawItem method isn't being called for the SBT_OWNERDRAW section.

    I'm using MSVC on W2K BTW :).

    Any ideas?

    John

    Reply
  • what is "m_bRvStatOk, m_Widths ?

    Posted by Legacy on 09/23/2002 12:00am

    Originally posted by: Sheroku

    what is "m_bRvStatOk, m_Widths ?

    Reply
  • To Girish and Steve

    Posted by Legacy on 07/11/2002 12:00am

    Originally posted by: Robert Cherenek

    You guys are awesome...

    I added your code Girish and it worked like a charm....

    but what about my resizable dialog? Steve to the rescue....

    BTW, I used the implementation here for the resizeable dialog class from CodeGuru - "Dialog Resize Helper" - from Stephan Keil in the Dialog section - and then Steve's resize stuff. I dropped it in my CDialog::OnSize()like so:

    void CMyDlg::OnSize(UINT nType, int cx, int cy)
    {
    CDialog::OnSize(nType, cx, cy);

    // FIX - don't run through this the first time, or
    // Release version will produce a bug...
    // So, just check for the existence of any DLG item...

    if (GetDlgItem(IDC_LIST3))
    {
    // From Stephan Kriel...
    m_resizeHelper.OnSize();

    // Resize Stat-Bar from Steve Maier
    CRect rct;
    int y = cy;

    m_Widths[0] = cx / 4;
    m_Widths[1] = cx / 2;
    m_Widths[2] = cx - m_Widths[0];
    m_Widths[3] = -1;

    m_StatBar.GetWindowRect(rct);
    y -= rct.Height();
    m_StatBar.MoveWindow(0,cx,y,cx,TRUE);
    m_StatBar.SetParts( 4, m_Widths);
    }
    }

    Thanks again,

    Robert Cherenek

    Reply
  • How do i overload the DRAWITEMSTRUCT?

    Posted by Legacy on 10/25/2001 12:00am

    Originally posted by: Bj�rn Malde

    The debugger tells me to overload the DRAWITEMSTRUCT, can you please tell me how i do that?

    Malde

    Reply
  • It's good. but linking with tooltip may be ?...

    Posted by Legacy on 01/26/2001 12:00am

    Originally posted by: Park KyungJoo

    How can I handle the message for tooltip?
    

    Reply
  • Ondraw draws over other Ownerdrawn Controls HELP

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

    Originally posted by: Peter

    hi,
    I have used your code to put a status bar on a dialog. I have also used
    another class in found in codeguru called csxButton to put pics on buttons:
    m_SearchCtrl.SubclassDlgItem(IDC_SEARCH,this);
    m_SearchCtrl.SetIcon(IDI_SEARCH,16,16);
    That put the icons on the button (Ownerdrawn). However now that i am using
    your code to put on bitmap on the statusbar it is drawning this bitmap to
    all my control buttons that are owner drawn.
    So basically i just want to bitmap to appear in the status bar and not to
    overwrite the other ownerdrawn controls.
    I would very appreciate any help u could give me
    .
    Cheers
    peter

    Reply
  • Change for resizable dialogs

    Posted by Legacy on 08/21/1999 12:00am

    Originally posted by: Steve Maier

    First I wanted to say nice job with this.

    Some people like to use resizable dialogs for their applications. I have done that quite a few times in the past when SDI/MDI apps were "forced" to be document/view architecture.

    When you add what Girish had earlier and then in the OnSize add what I have below you will have your status bar resizing anytime the window gets resized. You have to recalculate the widths and call the SetParts function and also move the window.

    Also Girish forgot the definition if m_Widths which is an array of 4 ints. (int m_Widths[4];)


    void CMyDlg::OnSize(UINT nType, int cx, int cy)
    {
    CDialog::OnSize(nType, cx, cy);

    // done to not give error on first resize
    if(m_StatBar.m_hWnd!=0)
    {
    CRect rct;
    int y=cy;

    m_Widths[0] = cx / 4;
    m_Widths[1] = cx / 2;
    m_Widths[2] = cx - m_Widths[0];
    m_Widths[3] = -1;

    m_StatBar.GetWindowRect(rct);
    y -= rct.Height();
    m_StatBar.MoveWindow(0,cx,y,cx,TRUE);
    m_StatBar.SetParts( 4, m_Widths);
    }
    }


    Steve Maier


    Reply
  • What about CDialogBars ?

    Posted by Legacy on 08/05/1999 12:00am

    Originally posted by: Van Lierde Peggy

    Hi,

    It is also possible to attach this statusbar to a
    floating dialogbar ? (I already have an OnInitDialogBar)

    Thanks,
    Peggy.

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

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date