Click here to Skip to main content
Licence CPOL
First Posted 16 Jul 2002
Views 68,351
Bookmarked 34 times

Command routing beyond a split frame

By | 16 Jul 2002 | Article
Command routing and UI updates for inactive views in a split frame.

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 c = 0; c < cc; c++)
        {
                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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Bartosz Bien

Team Leader
SPIN, Techland
Poland Poland

Member

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

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionCompiling error PinmemberMichael Klim14:57 1 Mar '09  
AnswerRe: Compiling error PinmemberBartosz Bien21:00 1 Mar '09  
AnswerRe: Compiling error PinmemberBartosz Bien9:30 2 Mar '09  
GeneralRe: Compiling error PinmemberMichael Klim12:59 2 Mar '09  
GeneralCommand routing Pinmembersdancer750:05 10 Jul '07  
GeneralPerfect! PinmemberJohn Simmons / outlaw programmer10:20 30 Nov '06  
GeneralRe: Perfect! PinmemberBartosz Bien10:43 30 Nov '06  
GeneralThankyou. Exactly what I wanted :) PinmemberGautam Jain4:03 28 Jul '06  
GeneralMFC Print preview Pinmembergowharjan21:11 26 Apr '05  
GeneralWell done... thanks Pinmemberhw7704115:46 15 Feb '05  
QuestionTypo? PinmemberMichael Hendrickx13:48 21 Oct '04  
AnswerRe: Typo? PinmemberBartosz Bien23:19 23 Oct '04  
Generalbrilliant PinmemberDomagoj11:19 23 Jun '04  
GeneralAnother thanks! PinmemberCarl Smigielski18:41 18 Sep '02  
GeneralThanks PinmemberJohn Gilbert8:58 27 Aug '02  
Thanks for the explanation. This information will definately get me going on the right track. I have a user who surely does NOT want to have to click on a specific view to activate buttons on the toolbar.
 
Thanks again Blush | :O

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120604.1 | Last Updated 17 Jul 2002
Article Copyright 2002 by Bartosz Bien
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid