-
January 18th, 2011, 01:37 PM
#1
[RESOLVED] Trouble with MDI GetSubMenu
I have a MDI program that is setup to support multiple languages. This app is configured to allow the operator to swap the language on-the-fly and all the menus/dialogs/etc will automatically switch to the newly selected language.
There are multiple types of document / view classes, and each class has its own menu. Also, I have a function that will return the translation (for the selected language) that is keyed off of the operator specified language.
Everything works fine when I have only 1 document open, but if there are 2 documents, then the program crashes (because GetSubMenu returns a NULL) when I switch to the 2nd document.
Each CScrollView type that I have uses a function such as OnActivateView bellow...
Code:
void CDocType1View::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
{
if (bActivate)
MainFramePtr->ShowType1Tools(); // changes the toolbar just bellow the menu
CScrollView::OnActivateView(bActivate, pActivateView, pDeactiveView);
if (bActivate && (nPrevLang != larray.nLangIdx))
RebuildMenu();
}
nPrevLang is a private int variable for CDocType1View
larray is a structure containing all my translations, a function "L" that return the translated text, and nLangIdx which keeps track of the selected language
The problem is in RebuildMenu(), when I first assign submenu2 (in the "Edit" section)...
Code:
void CDocType1View::RebuildMenu()
{
if (nPrevLang == larray.nLangIdx)
return;
nPrevLang = larray.nLangIdx;
CMenu *pMenu = AfxGetApp()->m_pMainWnd->GetMenu(),
*submenu = NULL,
*submenu2 = NULL,
*submenu3 = NULL,
*submenu4 = NULL;
CString szTemp;
// File
submenu = pMenu->GetSubMenu(0);
szTemp = larray.L(_T("&File"));
pMenu->ModifyMenu(0, MF_BYPOSITION, MF_STRING, szTemp);
szTemp = larray.L(_T("&Open...\tCtrl O"));
submenu->ModifyMenu(ID_FILE_OPEN, MF_BYCOMMAND, ID_FILE_OPEN, szTemp);
szTemp = larray.L(_T("&Print...\tCtrl P"));
submenu->ModifyMenu(ID_FILE_PRINT, MF_BYCOMMAND, ID_FILE_PRINT, szTemp);
szTemp = larray.L(_T("Print Pre&view"));
submenu->ModifyMenu(ID_FILE_PRINT_PREVIEW, MF_BYCOMMAND, ID_FILE_PRINT_PREVIEW, szTemp);
szTemp = larray.L(_T("P&rint Setup..."));
submenu->ModifyMenu(ID_FILE_PRINT_SETUP, MF_BYCOMMAND, ID_FILE_PRINT_SETUP, szTemp);
szTemp = larray.L(_T("E&xit"));
submenu->ModifyMenu(ID_APP_EXIT, MF_BYCOMMAND, ID_APP_EXIT, szTemp);
// Edit
submenu = pMenu->GetSubMenu(1);
szTemp = larray.L(_T("&Edit"));
pMenu->ModifyMenu(1, MF_BYPOSITION, MF_STRING, szTemp);
szTemp = larray.L(_T("Change Co&mments\tQ"));
submenu->ModifyMenu(ID_EDIT_CHANGECOMMENTS, MF_BYCOMMAND, ID_EDIT_CHANGECOMMENTS, szTemp);
submenu2 = submenu->GetSubMenu(1);
// this is where I'm failing on the 2nd document initialization, GetSubMenu return NULL
szTemp = larray.L(_T("Grouping"));
submenu->ModifyMenu(1, MF_BYPOSITION, MF_STRING, szTemp);
szTemp = larray.L(_T("Group 1"));
submenu2->ModifyMenu(ID_EDIT_GROUP1, MF_BYCOMMAND, ID_EDIT_GROUP1, szTemp);
szTemp = larray.L(_T("Group 2"));
submenu2->ModifyMenu(ID_EDIT_GROUP2, MF_BYCOMMAND, ID_EDIT_GROUP2, szTemp);
submenu2 = submenu->GetSubMenu(2);
szTemp = larray.L(_T("Typing"));
submenu->ModifyMenu(2, MF_BYPOSITION, MF_STRING, szTemp);
szTemp = larray.L(_T("Type 1"));
submenu2->ModifyMenu(ID_EDIT_TYPE1, MF_BYCOMMAND, ID_EDIT_TYPE1, szTemp);
szTemp = larray.L(_T("Type 2"));
submenu2->ModifyMenu(ID_EDIT_TYPE2, MF_BYCOMMAND, ID_EDIT_TYPE2, szTemp);
// ... I have clipped the rest of the code between the "Edit->Typing" through "Help", but it is very similar in style and substance. There are more cascades of menus that require me to use 4 submenu pointers.
// Help
submenu = pMenu->GetSubMenu(5);
szTemp = larray.L(_T("&Help"));
pMenu->ModifyMenu(5, MF_BYPOSITION, MF_STRING, szTemp);
szTemp = larray.L(_T("&Help Topics"));
submenu->ModifyMenu(ID_HELP_FINDER, MF_BYCOMMAND, ID_HELP_FINDER, szTemp);
szTemp = larray.L(_T("&About Display..."));
submenu->ModifyMenu(ID_APP_ABOUT, MF_BYCOMMAND, ID_APP_ABOUT, szTemp);
}
Can anyone tell me why this is failing when I switch to my 2nd document / view?
-
January 18th, 2011, 01:52 PM
#2
Re: Trouble with MDI GetSubMenu
I'd suggest you to redesign...
It's a very bad idea to hard code the texts (not only for menus!). You should just load the menu for appropriate language and destroy the existent one after you changed the language.
Victor Nijegorodov
-
January 18th, 2011, 01:59 PM
#3
Re: Trouble with MDI GetSubMenu
The translations are not hard coded. There is a database that the operator is able to modify so that they can have their own "custom" translations if need be. Because of that, I can't really create separate resources for different languages... there are far too many possibilities and I would have to re-deploy any time someone wanted to tweak their wording.
-
January 18th, 2011, 02:07 PM
#4
Re: Trouble with MDI GetSubMenu
If it were me then, I'd probably set up the CCmdUI update mechanism, call GetText() when it's about to display, look up the value in the database then use SetText() to display the command in the correct language.
-
January 18th, 2011, 02:08 PM
#5
Re: Trouble with MDI GetSubMenu
Originally Posted by vandy_mike
Each CScrollView type that I have uses a function such as OnActivateView bellow...
Code:
void CDocType1View::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
{
if (bActivate)
MainFramePtr->ShowType1Tools(); // changes the toolbar just bellow the menu
CScrollView::OnActivateView(bActivate, pActivateView, pDeactiveView);
if (bActivate && (nPrevLang != larray.nLangIdx))
RebuildMenu();
}
Why don't you check the view to be activated? (it sounds like you are trying to RebuildMenu for the deactivated view too!)
Victor Nijegorodov
-
January 18th, 2011, 02:10 PM
#6
Re: Trouble with MDI GetSubMenu
Originally Posted by GCDEF
If it were me then, I'd probably set up the CCmdUI update mechanism, call GetText() when it's about to display, look up the value in the database then use SetText() to display the command in the correct language.
Wouldn't that just update the text once you mouse over? I want the text to change as soon as the operator changes from English -> Spanish (etc.), not when they actually go through the menu system.
-
January 18th, 2011, 02:13 PM
#7
Re: Trouble with MDI GetSubMenu
Originally Posted by vandy_mike
Wouldn't that just update the text once you mouse over? I want the text to change as soon as the operator changes from English -> Spanish (etc.), not when they actually go through the menu system.
It would change the text whenever the menu item was about to be displayed. It's not necessary to change the text on items they can't see. All you'd need to do is have the correct database or translation table in place and the OnUpdate handler would ensure the correct text was displayed whenever necessary.
-
January 18th, 2011, 02:13 PM
#8
Re: Trouble with MDI GetSubMenu
Originally Posted by VictorN
Why don't you check the view to be activated? (it sounds like you are trying to RebuildMenu for the deactivated view too!)
Isn't this what I'm doing in "OnActivateView" right before the call to "RebuildMenu"? I would think that the condition of bActivate == TRUE would take care of this.
Originally Posted by vandy_mike
Code:
void CDocType1View::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)
{
if (bActivate)
MainFramePtr->ShowType1Tools(); // changes the toolbar just bellow the menu
CScrollView::OnActivateView(bActivate, pActivateView, pDeactiveView);
if (bActivate && (nPrevLang != larray.nLangIdx))
RebuildMenu();
}
-
January 18th, 2011, 02:21 PM
#9
Re: Trouble with MDI GetSubMenu
Originally Posted by vandy_mike
Isn't this what I'm doing in "OnActivateView" right before the call to "RebuildMenu"? I would think that the condition of bActivate == TRUE would take care of this.
No.
You should also check the (pActivateView == this) condition.
Victor Nijegorodov
-
January 18th, 2011, 02:42 PM
#10
Re: Trouble with MDI GetSubMenu
Originally Posted by VictorN
No.
You should also check the (pActivateView == this) condition.
This had no impact at all. It looks like my check to bActivate was probably sufficient... but I'm still getting a crash.
-
January 18th, 2011, 02:53 PM
#11
Re: Trouble with MDI GetSubMenu
Originally Posted by GCDEF
It would change the text whenever the menu item was about to be displayed. It's not necessary to change the text on items they can't see. All you'd need to do is have the correct database or translation table in place and the OnUpdate handler would ensure the correct text was displayed whenever necessary.
so then you would suggest changing ALL of the functions such as...
Code:
void CDocType1View::OnUpdateEditGroup1(CCmdUI *pCmdUI)
{
CMenu *pMenu = AfxGetApp()->m_pMainWnd->GetMenu();
pCmdUI->Enable(bAllowGrouping);
pMenu->CheckMenuItem(ID_EDIT_GROUP1, ((bAllowGrouping && bIsGroup1) ? MF_CHECKED : MF_UNCHECKED));
}
to...
Code:
void CDocType1View::OnUpdateEditGroup1(CCmdUI *pCmdUI)
{
CString szCurrentText;
CMenu *pMenu = AfxGetApp()->m_pMainWnd->GetMenu();
pCmdUI->Enable(bAllowGrouping);
pMenu->GetMenuString(ID_EDIT_GROUP1, szCurrentText, 255, MF_BYCOMMAND);
szCurrentText = larray.L(szCurrentText);
// either
pCmdUI->SetText(szCurrentText);
// or
pMenu->ModifyMenu(ID_EDIT_GROUP1, MF_BYCOMMAND, ID_EDIT_GROUP1, szCurrentText);
pMenu->CheckMenuItem(ID_EDIT_GROUP1, ((bAllowGrouping && bIsGroup1) ? MF_CHECKED : MF_UNCHECKED));
}
I think this would only update when the operator went to that section of the menu. So the menu would be a strange combination of English / Spanish (etc.) until the operator had moused-over each item.
-
January 18th, 2011, 03:03 PM
#12
Re: Trouble with MDI GetSubMenu
Originally Posted by vandy_mike
so then you would suggest changing ALL of the functions such as...
Code:
void CDocType1View::OnUpdateEditGroup1(CCmdUI *pCmdUI)
{
CMenu *pMenu = AfxGetApp()->m_pMainWnd->GetMenu();
pCmdUI->Enable(bAllowGrouping);
pMenu->CheckMenuItem(ID_EDIT_GROUP1, ((bAllowGrouping && bIsGroup1) ? MF_CHECKED : MF_UNCHECKED));
}
to...
Code:
void CDocType1View::OnUpdateEditGroup1(CCmdUI *pCmdUI)
{
CString szCurrentText;
CMenu *pMenu = AfxGetApp()->m_pMainWnd->GetMenu();
pCmdUI->Enable(bAllowGrouping);
pMenu->GetMenuString(ID_EDIT_GROUP1, szCurrentText, 255, MF_BYCOMMAND);
szCurrentText = larray.L(szCurrentText);
// either
pCmdUI->SetText(szCurrentText);
// or
pMenu->ModifyMenu(ID_EDIT_GROUP1, MF_BYCOMMAND, ID_EDIT_GROUP1, szCurrentText);
pMenu->CheckMenuItem(ID_EDIT_GROUP1, ((bAllowGrouping && bIsGroup1) ? MF_CHECKED : MF_UNCHECKED));
}
I think this would only update when the operator went to that section of the menu. So the menu would be a strange combination of English / Spanish (etc.) until the operator had moused-over each item.
Not really. You seem to be missing that the OnUpdate handler is called before the menu is displayed so you could change the text to whatever you want before the user sees it.
I would just add a line like
Code:
pCmdUI->SetText(TranslateText(pCmdUI->GetText());
where TranslateText would be a function that does the lookup and translation in your app.
-
January 18th, 2011, 03:13 PM
#13
Re: Trouble with MDI GetSubMenu
The only problem with CCmdUI update mechanism is it won't update the menu bar items.
Victor Nijegorodov
-
January 18th, 2011, 05:56 PM
#14
Re: Trouble with MDI GetSubMenu
Originally Posted by GCDEF
Not really. You seem to be missing that the OnUpdate handler is called before the menu is displayed so you could change the text to whatever you want before the user sees it.
I would just add a line like
Code:
pCmdUI->SetText(TranslateText(pCmdUI->GetText());
where TranslateText would be a function that does the lookup and translation in your app.
First...
pCmdUI->GetText() does not exist... so I would still have to do something like GetMenuString.
Second...
That doesn't help me for "pop-up" menus, only the items in the pop-up.
The root problem is that I can't access my "nested" pop-up menus.
For instance, if there is a menu pop-up item called "Operations" as a subset of "Edit", and there is a menu pop-up item called "Math" inside operations... and Math has 2 menu items called "Add" (ID_OPER_MATH_ADD) and "Subtract" (ID_OPER_MATH_SUB)...
Edit -> Operations -> Math -> Add
Edit -> Operations -> Math -> Subtract
I can translate these using ModifyMenu from my originally posted code, such as...
Code:
szTemp = larray.L(_T("Add"));
pMenu->ModifyMenu(ID_OPER_MATH_ADD, MF_BYCOMMAND, ID_OPER_MATH_ADD, szTemp);
//pMenu is OK whenever using MF_BYCOMMAND
And I can translate Edit such as...
Code:
szTemp = larray.L(_T("&Edit"));
pMenu->ModifyMenu(1, MF_BYPOSITION, MF_STRING, szTemp);
//using pMenu so no problem
And I can translate Operations such as...
Code:
submenu = pMenu->GetSubMenu(1);// Edit submenu
szTemp = larray.L(_T("Operations"));
submenu->ModifyMenu(0, MF_BYPOSITION, MF_STRING, szTemp);
//succeeds at getting the submenu of pMenu
But I fail (2nd document/view) when I try to translate Math...
Code:
submenu2 = submenu ->GetSubMenu(0);// Operations submenu
szTemp = larray.L(_T("Math"));
submenu2->ModifyMenu(0, MF_BYPOSITION, MF_STRING, szTemp);
//fails to get submenu2 from the pointer to submenu
As I said, this all works correctly for the 1st document/view, but when I change to the 2nd window that I have open... my application crashes.
-
January 18th, 2011, 06:06 PM
#15
Re: Trouble with MDI GetSubMenu
Originally Posted by vandy_mike
...
As I said, this all works correctly for the 1st document/view, but when I change to the 2nd window that I have open... my application crashes.
Perhaps, because the 2nd document uses another menu?
Victor Nijegorodov
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|