Toolbars and Statusbars on Dialogs

By default, MFC only allows you to add Toolbars and Statusbars on CFrameWnd subclassed objects. This is great, but if you want to add toolbars on dialogs, you're like an idiot, because you can't do this easily.

The first problem is that every handler function expect the parent to be a CFrameWnd subclassed object, and another one is that you can only show tooltips or statusbar message when the dialog is in IDLE state. In fact, for the control bars to function properly, you'll have to catch some of the messages that the frame window uses.

I'll have to dig a lot in the documentation to find something that helps me doing that. One issue was shown me by Mihai Filimon (see articles posted on Monday 16 march 1998), which was fine, but not very "clean" since you have to make room for the bar with an invisible static object. (I thanks a lot him for showing the light at the end of the tunnel).

Let me expose you what to do if you want a toolbar (fixed, there is no other way possible) and a menu which can talk with any StatusBar in the application (even in the dialog but I think it will be the subject of another article).

I’ll only expose you how to add a Toolbar on a dialog (the menu is obvious since you only have to define one and add it on the resource editor).

First, you’ll have to develop your dialog (with its object) without bothering the place of the ToolBar, and subclass the CDialog class to use this dialog template (nothing new here).

Then, add this code on the CDialog::OnInitDialog function (the m_wndToolBar variable is of type CToolBarEx) :


BOOL CMyDlg::OnInitDialog() 
{
	// TODO: Add extra initialization here
	CDialog::OnInitDialog();

	// Add the ToolBar.
	if (!m_wndToolBar.Create( this ) ||
		!m_wndToolBar.LoadToolBar(IDR_CORPS_EMIS) )
	{
		TRACE0("Failed to create toolbar\n");
		return -1;      // fail to create
	}

	// TODO: Remove this if you don't want tool tips or a resizeable toolbar
	m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
		CBRS_TOOLTIPS | CBRS_FLYBY  );

// We need to resize the dialog to make room for control bars.
	// First, figure out how big the control bars are.
	CRect rcClientStart;
	CRect rcClientNow;
	GetClientRect(rcClientStart);
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 
				   0, reposQuery, rcClientNow);
	
	// Now move all the controls so they are in the same relative
	// position within the remaining client area as they would be
	// with no control bars.
	CPoint ptOffset(rcClientNow.left - rcClientStart.left,
					rcClientNow.top - rcClientStart.top); 

	CRect  rcChild;					
	CWnd* pwndChild = GetWindow(GW_CHILD);
	while (pwndChild)
	{                               
		pwndChild->GetWindowRect(rcChild);
		ScreenToClient(rcChild);
		rcChild.OffsetRect(ptOffset);
		pwndChild->MoveWindow(rcChild, FALSE);
		pwndChild = pwndChild->GetNextWindow();
	}

	// Adjust the dialog window dimensions
	CRect rcWindow;
	GetWindowRect(rcWindow);
	rcWindow.right += rcClientStart.Width() - rcClientNow.Width();
	rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();
	MoveWindow(rcWindow, FALSE);
	
	// And position the control bars
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

You can see that it is not obvious (I found it in a more complicated sample called DLGCBR32, and I work a lot to find out the functions that are compulsory, and the others)

At that point, you have only a Toolbar in top of your dialog (you see that any toolbar can fit the requirements to be shown in a dialog, since the preceding code is generic enough). You can have many toolbars in your dialog, but you must manage the positions by yourself.

Now, if you want tooltips on your Toolbar, you must handle the following messages TTN_NEEDTEXTA and TTN_NEEDTEXTW (for both ANSI and Unicode characters sets), in the following way :

1. Add the message handlers declaration...


BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
	...
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()

2. Declare the function in your header file that way :


// Generated message map functions
//{{AFX_MSG(CMyDlg)
afx_msg BOOL OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG

3. And finally code your OnToolTipText function that way (comes from MFC Sample) :


BOOL CMyDlg::OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult)
{
	ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);

	// allow top level routing frame to handle the message
	if (GetRoutingFrame() != NULL)
		return FALSE;

	// need to handle both ANSI and UNICODE versions of the message
	TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
	TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
	TCHAR szFullText[256];
	CString cstTipText;
	CString cstStatusText;

	UINT nID = pNMHDR->idFrom;
	if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
		pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
	{
		// idFrom is actually the HWND of the tool
		nID = ((UINT)(WORD)::GetDlgCtrlID((HWND)nID));
	}

	if (nID != 0) // will be zero on a separator
	{
		AfxLoadString(nID, szFullText);
			// this is the command id, not the button index
		AfxExtractSubString(cstTipText, szFullText, 1, '\n');
		AfxExtractSubString(cstStatusText, szFullText, 0, '\n');
	}

	// Non-UNICODE Strings only are shown in the tooltip window...
	if (pNMHDR->code == TTN_NEEDTEXTA)
		lstrcpyn(pTTTA->szText, cstTipText,
            (sizeof(pTTTA->szText)/sizeof(pTTTA->szText[0])));
	else
		_mbstowcsz(pTTTW->szText, cstTipText,
            (sizeof(pTTTW->szText)/sizeof(pTTTW->szText[0])));
	*pResult = 0;

	// bring the tooltip window above other popup windows
	::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
		SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);


	return TRUE;    // message was handled
}

Now you have a toolbar with tooltips (the text shown in the tooltip box is defined the classic way, with the resource editor). (pheeew ;-) ).

Now, if you want the mainframe's status bar to display the text that would normally be prompted, the only line (right, the ONLY one) of code you have to add is in the above function (it is useful for System modal dialog boxes since they are usually small), just before the return statement (it also assume that m_wndStatusBar is public) :


// Display the text in the mainframe's status bar (assumes the Help pane text
// is at the index zero.
	((CMainFrame*)GetParent())->m_wndStatusBar.SetPaneText(0, cstStatusText);

That's all for today.

No, let me tell you just one more thing, if you want your dialog menu to display text in the mainframe's status bar (on in any other status bar you have created) you can add the following code to the handler of WM_MENUSELECT (window-type handler) :


void CMyDlg::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu) 
{
	CDialog::OnMenuSelect(nItemID, nFlags, hSysMenu);
	
	TCHAR szFullText[256];
	CString cstStatusText;
	// TODO: Add your message handler code here
	// Displays in the mainframe's status bar
	if (nItemID != 0) // will be zero on a separator
	{
		AfxLoadString(nItemID, szFullText);
			// this is the command id, not the button index
		AfxExtractSubString(cstStatusText, szFullText, 0, '\n');
		((CMainFrame*)GetParent())->m_wndStatusBar.SetPaneText(0,cstStatusText);
}
}


Note that you can't use the ON_UPDATE_COMMAND_UI message on this toolbar, since it can only be refresh when the dialog enters in idle state. To do so, you must subclass the CToolBar (or CStatusBar) class - in CMyToolBar for instance -, add the message handler for WM_IDLEUPDATECMDUI, and write the following code in this function :


/////////////////////////////////////////////////////////////////////////////
// CMyToolBar::OnIdleUpdateCmdUI
//	OnIdleUpdateCmdUI handles the WM_IDLEUPDATECMDUI message, which is 
//	used to update the status of user-interface elements within the MFC 
//	framework.
//
// 	We have to get a little tricky here: CToolBar::OnUpdateCmdUI 
//	expects a CFrameWnd pointer as its first parameter.  However, it
//	doesn't do anything but pass the parameter on to another function
//	which only requires a CCmdTarget pointer.  We can get a CWnd pointer
//	to the parent window, which is a CCmdTarget, but may not be a 
//	CFrameWnd.  So, to make CToolBar::OnUpdateCmdUI happy, we will call
//	our CWnd pointer a CFrameWnd pointer temporarily.  	

LRESULT CMyToolBar::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM) 
{
	if (IsWindowVisible()) 
	{
		CFrameWnd *pParent = (CFrameWnd *)GetParent();
		if (pParent)
			OnUpdateCmdUI(pParent, (BOOL)wParam);
	}
	return 0L;
}


In order to have the toolbar updated you MUST override the ContinueModal() function that way:


BOOL CMyDlg::ContinueModal()
{
    m_wndToolbar.SendMessage( WM_IDLEUPDATECMDUI, WPARAM(TRUE), 0);


    return CDialog::ContinueModal();
}


For AfxLoadString to compile you must Include the file "Afxpriv.h" at the beginning of the CPP file.



Comments

  • Brief editorial tells the indisputable details on gucci and the way it could harm owners.

    Posted by emeseesip on 05/06/2013 04:39pm

    Basically The Most Detailed nike Guidebook You Ever Read Or else Your Money Back [url=http://www.guccija.biz/]グッチ 財布[/url] Omg, astounding solution. Your business gotta check out adidas immediately while it is still available . . . [url=http://www.guccija.biz/]グッチ キーケース[/url] adidas assists all of us by integrating several exceptional capabilities and options. It is a unvaluable thing for all follower of gucci. [url=http://www.guccija.biz/]gucci バッグ[/url] Impartial website displays 2 fresh stuff on gucci that no company is mentioning. [url=http://www.chanelja.biz/]シャネル マトラッセ[/url] That explains why no company is talking over nike and accordingly the things that one should begin doing immediately. [url=http://www.chanelja.biz/]シャネル チェーンウォレット[/url] Recent questions on nike answered and as a consequence reasons why you would need to analyze each message of this specific article. [url=http://www.chanelja.biz/]財布 chanel[/url] An overview of gucci you could potentially take full advantage of starting up today.[url=http://www.nikeja.biz/]ナイキ[/url] Recommendations on how to discover everything that there is to know related to adidas in Some easy ways.

    Reply
  • Short article uncovers the proven facts about gucci and ways in which it can certainly have an effect on your corporation.

    Posted by incockDak on 04/25/2013 02:43am

    Beginner questions about nike addressed and reasons why you must definitely study each and every term of this specific report. [url=http://www.mizunogoruhujp.com/]ミズノ[/url] The key reason why almost anything you may have discovered about nike is truly completely wrong and exactly what you need understand.[url=http://www.mizunogoruhujp.com/ミズノ-ゴルフクラブ-c-1.html]ミズノ mp[/url] Creative questions about mizuno answered and in addition the reason why you will want to read in detail every concept of this specific story. [url=http://www.mizunogoruhujp.com/ゴルフグローブ-c-33.html]グローブ ミズノ[/url] Be aware of who is expounding on nike and as to why you should fear. [url=http://www.mizunogoruhujp.com/ゴルフバッグ-c-7.html]ミズノ[/url] Supplies and formation throughout Nevada - nike simply leaves without good-bye [url=http://www.mizunogoruhu.com/]ミズノ アイアン[/url] The Tips To Gain knowledge mizuno And Also How One Might Connect with The nike Top dogs [url=http://www.mizunogoruhu.com/ミズノmizuno-クラブ-c-4.html]ミズノ mp[/url] Whatever the pros don't seem to be thinking regarding nike and also the way it is relevant to you. [url=http://www.mizunogoruhu.com/ミズノmizuno-アイアン-c-3.html]ミズノ[/url] The essential principles of nike that you could reap the benefits of starting off today. [url=http://www.mizunogoruhu.com/ミズノmizuno-アイアン-c-3.html]ミズノ アイアン[/url] The Secret rule the nike-arena Is Quite Clear-cut! [url=http://www.mizunogoruhu.com/ミズノmizuno-バッグ-c-5.html]ミズノゴルフ[/url] Whatever the industry professionals won't be actually saying around mizuno along with the way this impacts on you.

    Reply
  • Bizarre article gives you the small print around mizuno that just one or two people know of.

    Posted by icoppyapedcap on 04/25/2013 01:06am

    JxpXqoBmvIrc [url=http://www.nikeyasuijp.com/]nike[/url]WchXzzAmtJvs [url=http://www.nikeyasuijp.com/nike-air-force1エアフォース1-c-14.html]ナイキ フリ[/url]BvcNjeCdoYyu [url=http://www.nikeyasuijp.com/nike-air-maxエアマックス-c-12.html]ナイキランニング[/url]EtgYbhZedYee [url=http://www.nikeyasuijp.com/nike-air-jordanエア-ジョーダン-c-13.html]nike air jordan[/url]ScnRffFjgOwm

    Reply
  • New one

    Posted by snareenactina on 11/12/2012 04:43pm

    Economists, finance professors, options and derivatives experts and business school professors have dropped the ball completely when it comes to the financial crisis. Students need to tell their professors to speak out. workeriuri The Importance of Community rychlá+půjčka+bez+registru+bez+dokládání+příjmu+půjčky+ihned+na+ruku+půjčky+se+zástavou+nemovitostí+a+mnoho+jiných+najdete+u+nás+wwwℑ.x=8ℑ.y=8 "spodocephala rackets assimilative mezky pensions

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

Top White Papers and Webcasts

  • IBM Worklight is a mobile application development platform that lets you extend your business to mobile devices. It is designed to provide an open, comprehensive platform to build, run and manage HTML5, hybrid and native mobile apps.

  • Companies must routinely transfer files and share data to run their business, work with partners, and speed operations. However, many find the traditional approach to file transfer lacks necessary security, is too complex and difficult to manage, does not support the levels of automation needed, and breaks down when addressing the file transfer requirements of new areas like Big Data analytics and mobile applications. This QuinStreet SmartSelect discusses how the changing business environment is making the use …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds