• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 205
  • Last Modified:

Splitters, Views, and Menus

I have an app that has two splitter windows, one embedded inside the other so that three different views are visible at any given time. I noticed that my menu handlers and update handlers will only function corectly when I have given focus to the view that is supposed to handle them. For example, if I want view 1 to handle menu item 1 and update handler 1, I have to make sure view 1 has focus. If either view 2 or 3 has focus the handler and update handler do not respond. Is there a way to make this application know which view has a handler and update handler for each menu ID? Is this a command routing issue? The commands don't seem to get routed to all of the views.
0
JagerM
Asked:
JagerM
  • 2
1 Solution
 
jstolanCommented:
This is the way it's supposed to work.  Each view may have different ways of handling the same message.  For example if you have a CListView it may handle a menu item that says "Delete" very diffently from a CEditView.  

If you always want view 1 to handle a given message, you need to be able to pass it from view 2 to view 1.  This also goes for the Update messages.  For example you may have something like this:

void CView1::OnHandleMyMessage()
{
    // Do something
}

void CView1::OnUpdateMyMessage(CCmdUI* pCmdUI)
{
    // Handle update
}

Then in CView2 you would call the CView1 handlers

void CView1::OnHandleMyMessage()
{
    // Get pointer to view2
    CView2* pView2 = GetView2();
    pView2->OnHandleMyMessage();
}

void CView1::OnUpdateMyMessage(CCmdUI* pCmdUI)
{
    // Get pointer to view2
    CView2* pView2 = GetView2();
    pView2->OnUpdateMyMessage(pCmdUI);
}

0
 
jstolanCommented:
Oops

I see I made a typo.  The last two items should read:

void CView2::OnHandleMyMessage()
{
    // Get pointer to view1
    CView1* pView1 = GetView1();
    pView1->OnHandleMyMessage();
}

void CView2::OnUpdateMyMessage(CCmdUI* pCmdUI)
{
    // Get pointer to view1
    CView1* pView1 = GetView1();
    pView1->OnUpdateMyMessage(pCmdUI);
}

Also note that you will need to have some way of getting the pointers to the otherviews.  The ChildFrame is a good place to put these functions.
0
 
JagerMAuthor Commented:
This doesn't seem like a graceful way to handle it, but it's probably the right methodlology. I looked into overridding OnCmdMsg for the MainFrame and routing the messages to all Views, but this is protected in the View classes. It's also tricky because I'm swapping views in two of the splitter windows based on what's happening in the third.

I ended up using a global CMap object that essentially acts as a custom message map. I have an enumerated type:

enum EnViewType
{
VIEW_FILE,
VIEW_PROJECT,
VIEW_WORKGROUP
};

that I map to a View pointer. i.e.

CMap< EnViewType, EnViewType, CView *, CView *> g_mapMessages

In each view's OnCreate member, it registers with this global mapping.

CFileView::OnCreate
{
.
g_mapMessages.SetAt( VIEW_FILE, this );
.
}

I then handle every menu item and update handler in the MainFrame and route it to the appropriate view using this map. Now all of my menus are handled correctly no matter which view is active. Not to graceful either, but it works pretty well.

Thanks for the help.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now