5,138,728 members and growing! (16,625 online)
Email Password   helpLost your password?
Desktop Development » Document / View » General     Intermediate

Command routing beyond a split frame

By Bartosz Bien

Command routing and UI updates for inactive views in a split frame.
VC6, VC7, C++Windows, Win2K, WinXP, Visual Studio, MFC, Dev

Posted: 16 Jul 2002
Updated: 16 Jul 2002
Views: 43,560
Announcements



Search    
Advanced Search
Sitemap
14 votes for this Article.
Popularity: 5.24 Rating: 4.57 out of 5
0 votes, 0.0%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
0 votes, 0.0%
4
8 votes, 100.0%
5

Abstract

The article presents three simple methods of routing WM_COMMAND messages through a number of views in a split frame window. This simplifies dealing with the command routing and UI updates for inactive views.

Introduction to the problem

The standard framework route does not include inactive views, which causes toolbar buttons and menus to gray when their mother view is deactivated. Users are confused. I present three simple methods to bring their happiness back. :) All solutions base on overriding the CCmdTarget::OnCmdMsg function in the frame class. I assumed that this class is derived directly from CFrameWnd (SDI case), but these methods can be used with MDI child window as well.

In each case, the overridden function browses through a list of views and calls CCmdTarget::OnCmdMsg for each of them, passing the received arguments. If TRUE is returned, we can return – the message has undoubtedly been handled by the view and no further processing is needed. Naturally, the active view is excluded from this call, because it is to be processed by the base handler – this is the default case. You may place a base function call in the beginning of the overridden function body if you expect the messages to be successfully processed mostly by an active view, a frame itself or a CWinApp-derived object, as these three calls are made in the base CFrameWnd::OnCmdMsg implementation. Our custom routine should then be executed only if the base implementation returns FALSE.

Classic document/view case

The first quite obvious method is to use a list of views that is available in the CDocument class and accessible through the GetFirstViewPosition / GetNextView helper function pair. Along with the active view, this method browses all inactive ones, but you may filter the list as you wish to suit your application’s needs.

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra,
	AFX_CMDHANDLERINFO* pHandlerInfo) 
{
    CDocument *pDoc = GetActiveDocument();
    if(pDoc)
    {
	POSITION pos = pDoc->GetFirstViewPosition();
	CView *pView = NULL;
	while(pView = pDoc->GetNextView(pos))
	{
	    if(pView != GetActiveView()
		&& pView->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;
	}
    }

    return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

Splitter window case

What if we didn’t like to use any CDocument-derived class object at all? This may be the case, and the first method would then be useless. Yet, to achieve the routing goal, we don’t need a document, as we only have to get access to windows that process the message, i.e. the splitter panes. This is no hassle if you have an explicit splitter object – either as a pointer, or as a member in your frame class, which I find a common case. Simply use CSplitterWnd::GetPane and have it done! This case has also been hinted by Samuel Chow some time ago.

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra,
	AFX_CMDHANDLERINFO* pHandlerInfo) 
{
    if(m_wndSplitter.GetSafeHwnd())
    {
	int rc = m_wndSplitter.GetRowCount(),
	    cc = m_wndSplitter.GetColumnCount();

	for(int r = 0; r < rc; r++)
	    for(int r = 0; r <ec; r++)
	{
		CWnd *pWnd = m_wndSplitter.GetPane(r, c);
		if(pWnd != m_wndSplitter.GetActivePane()
		    && pWnd->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		    return TRUE;
        }
    }
    return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

A possibly universal case

A young eager mind would then like to have a universal handler, independent of existence of member splitters or even a document. Seeking inspiration in MFC sources, namely CView and CSplitterWnd classes, I noticed that they utilize standard pane IDs (see afxres.h) to get access to inactive views in a frame. And surely they use neither a document pointer, nor a splitter object directly! Now here comes the Holy Grail:

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra,
	AFX_CMDHANDLERINFO* pHandlerInfo) 
{
    for(UINT id = AFX_IDW_PANE_FIRST; id <= AFX_IDW_PANE_LAST; id++)
    {
	CWnd *pWnd = GetDescendantWindow(id, TRUE);
	if(pWnd && pWnd != GetActiveView()
	    && pWnd->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
	    return TRUE;
	}
    }
    return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

As with the first method, the handler doesn’t have to be called for all views, as the calls may be freely filtered. It may be even done dynamically, e.g. depending on nID or nCode values, but I’m afraid this would complicate the routing a bit too much. Such roundabout solutions should always be thought over twice – there are many straightforward methods of distributing the message handling among the existing command targets, and this is not the case.

There is no possibility that these snippets would solve all your trouble with MFC command message routing, but it may get you closer or simply bring you a little clue. Any comments and suggestions are warmly welcome.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Bartosz Bien


I’m a freelance software designer and developer living in a green district of Wrocław, a thirteen century old city located in southwestern Poland, known of its multicultural character, unique landmarks and events. The region has a great variety of opportunities, which allow me to realize myself in many pursuits.

I was born on Saturday, October 16th, 1976. Since then I’ve been engaged in various technical, scientific and cultural ventures, ranging from cosmology and environmental protection up to the bridge and highway management – not to mention prose writing or breeding huge exotic fish of prey. I’m keen on long walks and leisure cycling. I’ve been a member of Mensa Poland since 1998, and married since 2001 to my darling Doctor of Medicine. Our son was born on May 7th, 2005, and we're deeply focused on enjoying the pleasures of parentship.

My interests in artificial intelligence mostly concentrate on applying various intelligent techniques to games and transportation infrastructure management systems. Along with the complex design of such applications, I build up combinations of hybrid expert systems and learning methods to achieve the real-life AI. Utilized techniques include artificial neural networks, analytical processing and fuzzy controllers tuned with evolutionary algorithms. I’m also interested in general AI topics, intelligent houses, and astrophysics-related technologies.

My other professional achievements include a valuable experience in software creation. I feel fluent in applying object programming techniques, including object databases, to develop desktop and distributed applications, equipped with legible and elegant user interfaces. I also have the firsthand administrative knowledge of the Internet and intranet-based networks.

Personal homepage: http://bartoszbien.com

My company's homepage: http://spin.neostrada.pl
Occupation: Team Leader
Company: SPIN, Techland
Location: Poland Poland

Other popular Document / View articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 11 of 11 (Total in Forum: 11) (Refresh)FirstPrevNext
Subject  Author Date 
GeneralCommand routingmembersdancer751:05 10 Jul '07  
GeneralPerfect!memberJohn Simmons / outlaw programmer11:20 30 Nov '06  
GeneralRe: Perfect!memberBartosz Bien11:43 30 Nov '06  
GeneralThankyou. Exactly what I wanted :)memberGautam Jain5:03 28 Jul '06  
GeneralMFC Print previewmembergowharjan22:11 26 Apr '05  
GeneralWell done... thanksmemberhw7704116:46 15 Feb '05  
GeneralTypo?memberMichael Hendrickx14:48 21 Oct '04  
GeneralRe: Typo?memberBartosz Bien0:19 24 Oct '04  
GeneralbrilliantmemberDomagoj12:19 23 Jun '04  
GeneralAnother thanks!memberCarl Smigielski19:41 18 Sep '02  
GeneralThanksmemberJohn Gilbert9:58 27 Aug '02  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 16 Jul 2002
Editor: Chris Maunder
Copyright 2002 by Bartosz Bien
Everything else Copyright © CodeProject, 1999-2008
Web11 | Advertise on the Code Project