Problems with CMenu::ModifyMenu - c++

I'm using CMenu::ModifyMenu in the OnCreate method of my CFrameWnd derived class to change the captions on my menu to match the user language.
I'm using VC++ designer and the menu is declared in a .rc file.
For the MENUITEM elements I use it as follow:
m_wndMenu->ModifyMenu(ID_APP_EXIT, MF_BYCOMMAND, NULL, CString((LPWSTR) ID_APP_EXIT));
For the POPUP elements (that don't have an ID) I use it as follow:
m_wndMenu->ModifyMenu(0, MF_BYPOSITION | MF_STRING, NULL, CString((LPWSTR) ID_MENU_POPUP_FILE));
It works as expected to change the captions, but for the menu items that are initialy disabled when I change the caption they get enabled. How do I fix this?

You may have to explicitly disable the menu item and set tool tip text after a call to ModifyMenu. Using ModifyMenu will effectively destroy the previous menu item and create a new one. You are losing any settings and initialization from the resource file or otherwise that you had on the previous item or menu.
See remarks: http://msdn.microsoft.com/en-us/library/4tbfebs6(v=vs.80).aspx

for such scenario, better to use EnableMenuItem function, like this
m_wndMenu->EnableMenuItem(ID_APP_EXIT, MF_BYCOMMAND| MF_ENABLED);
this will work...

Related

How to Make a Simple GUI with DropDown Menus with C++

I am really struggling how to make a window with three selections of options. I currently have a setup that uses a CFileDialog object and have successfully implemented two dropdown menus and multiple check items.
What I want is to implement a pop up window that has the two drop down menus and the check boxes. If a certain item is selected in one of the dropdown menus then the file dialog is opened.
Currently I am trying to make a CWnd object and try to write code for it there.
CWnd myWindow;
BOOL VALUE = myWindow.Create(_T("DesktopApp"), _T("test"), WS_VISIBLE | WS_BORDER | WS_CAPTION,
RECT{ 100,100,400,400 },
myWindow.GetDesktopWindow(), 12);
myWindow.ShowWindow(SW_SHOWNORMAL);
if (VALUE == FALSE) {
return 0;
}
Every time I run this, it prematurely returns (VALUE == FALSE). Did I do something wrong? Is there a simpler way to create a window?
The first argument to CWnd::Create is the window class name. A class with the requested name must have been registered before it can be created.
It is common to register an application local class for the application's main window. MFC provides a convenient wrapper function (AfxRegisterWndClass) to register a window class.

How does the MFC PropertyGrid control work in the dialog editor in visual studio?

In the visual studio dialog editor i can add a MFC Property Grid control to the dailog. How can i customize its content, and set options like allowing the user to edit the contents of it when the program using it is running, or how i can change the contents of it using c++?
When i add something like a button or and edit control it displays on the dailog box when the program is running, while when i add a MFC Property Grid the dailog isnt even being displayed.
Here is a picture of the visual studio dialog editor and a MFC property control grid in the middle of the dailog with contents i dont know how to change.
Simple tutorial of CMFCPropertyGridCtrl:
1.Create a dialog-based MFC project, drag a CMFCPropertyGridCtrl into it, and adjust the size. Then change the ID for the control to IDC_MFCPROPERTYGRID_TEST, and use Add Varible to add a variable m_propertyGrid to the control. Change the setting of Notify to True.
Description Rows Count refers to the number of rows in the description section below.
Enable Description Area indicates whether to enable the following description function.
Enable Header indicates whether to start the header.
Mark Modified Properties indicates whether to highlight the changes.
2.Set interface
Add the following code in OnInitDialog()
HDITEM item;
item.cxy=120;
item.mask=HDI_WIDTH;
m_propertyGrid.GetHeaderCtrl().SetItem(0, new HDITEM(item));
Add content
Add the following code in OnInitDialog()
CMFCPropertyGridProperty* pProp2 = new CMFCPropertyGridProperty(
_T("choose"),
_T("select"),
_T(""));
pProp2->AddOption(_T("1"));
pProp2->AddOption(_T("2"));
pProp2->AddOption(_T("3"));
pProp2->AllowEdit(FALSE); //Editing of options is not allowed
m_propertyGrid.AddProperty(pProp2);
The three parameters passed in when calling the constructor are item name, default options and description text.
Also, you could add drop-down menu:
CMFCPropertyGridProperty* pProp2 = new CMFCPropertyGridProperty(
_T("choose"),
_T("select"),
_T(""));
pProp2->AddOption(_T("1"));
pProp2->AddOption(_T("2"));
pProp2->AddOption(_T("3"));
pProp2->AllowEdit(FALSE); //Editing of options is not allowed
m_propertyGrid.AddProperty(pProp2);
In addition, there are three similar projects:
CMFCPropertyGridColorProperty * pProp3 = new CMFCPropertyGridColorProperty(
_T("colour"), RGB(0, 111, 200));
m_propertyGrid.AddProperty(pProp3);
CMFCPropertyGridFileProperty * pProp4 = new CMFCPropertyGridFileProperty(
_T("open file"), TRUE, _T("D:\\test.txt"));
m_propertyGrid.AddProperty(pProp4);
LOGFONT font = { NULL };
CMFCPropertyGridFontProperty * pProp5 = new CMFCPropertyGridFontProperty(
_T("select font"), font);
m_propertyGrid.AddProperty(pProp5);
Finally, This is the final program running interface:

In MFC how to display list box on the BCN_DROPDOWN event of split button control

I am using VS2008.
I have MFC dialog based application with split button control.
I want to display a list box on the BCN_DROPDOWN event of split button control. I dont know how to achieve it?
Reference to the documentation of the CSplitButton class: https://msdn.microsoft.com/en-us/library/bb514109.aspx
If you want to change default behaviour then use the override:
BEGIN_MESSAGE_MAP(CMySplitButton,
CSplitButton)
ON_NOTIFY_REFLECT(BCN_DROPDOWN, &CMySplitButton::OnDropDown)
END_MESSAGE_MAP()
(...)
afx_msg void OnDropDown(NMHDR* pNMHDR, LRESULT* pResult);
You can in this function show your listbox or whatever you like.
If the listbox you refer to the actual submenu (3) as shown in the documentation, then add a menu: https://msdn.microsoft.com/en-us/library/4b6tafew.aspx and set the resource ID for that menu into SetDropDownMenu() function
void SetDropDownMenu(
UINT nMenuId,
UINT nSubMenuId);
Good luck :)
You must add your menu into a resource.
Ex:IDR_MENU_BUTTON_ANY
Declare some Resource symbols for submenu. It will change *.rc and resource.h.
Your resource will look like:
IDR_MENU_BUTTON_ANY
BEGIN
POPUP "SampleMenu"
BEGIN
MENUITEM "Sub1", ID_SUB_MENU_1
MENUITEM "Sub2", ID_SUB_MENU_2
END
END
When you initialize your dialog. You should insert some code as below:
//Your split button
CMFCSplitButton m_btnAny;
//Set dropdown menu
m_btnAny.SetDropDownMenu(IDR_MENU_BUTTON_ANY, 0);
More, I found the following link. The author provided an example. It may help you.
http://codexpert.ro/blog/2013/02/01/split-button-control/#comment-22983

C++ - MFC - Change text of a CMenu

Good morning everybody,
I created an application that manages multi-language. When I dynamically change the default language of the application, all the text of the different graphic components change very well excepted one component. I don't know why ?
I tried those lines for modifying the text of the menu title but it changes only if I put my mouse on this menu.
MENUITEMINFO info;
info.cbSize = sizeof(MENUITEMINFO);
info.fMask = MIIM_ID;
VERIFY(AfxGetMainWnd()->GetMenu()->GetMenuItemInfoA(0, &info, TRUE));
AfxGetMainWnd()->GetMenu()->ModifyMenuA(0, MF_STRING | MF_BYPOSITION, info.wID, theApp.vattingTranslation.GetDescription(256).c_str());
Why does it not refresh automatically my menu item "Système" ?
Thanks in advance
You need to call a DrawMenuBar function afterwards as specified in the ModifyMenu documentation:
The application must call the DrawMenuBar function whenever a menu
changes, whether the menu is in a displayed window.

How might I obtain the IContextMenu that is displayed in an IShellView context menu?

Building a file open dialog replacement. Much of it works now, but I would like to generate the view-mode drop-down for the toolbar directly from the shell view object.
Looking at IShellView2, I can see IShellView2::GetView() will give me the FOLDERVIEWMODE's supported. However, that doesn't give me the names of these modes, nor format that popup menu for me, nor immediately give me a way to actually set one of those modes (it would appear it is necessary to destroy the shell view window and create a replacement one for the current folder and specify the new FOLDERVIEWMODE desired... yeesh).
At any rate, if one right clicks on an IShellView window, one gets a context menu, the first submenu of which is exactly what I want to place in my drop-down toolbar button (ie. the "view" fly-out menu (e.g. Small Icons, Medium Icons, etc.)).
It seems like there ought to be a way to grab that submenu directly from the IShellView, rather than having to hardcode my values (and that way, if a given instance of IShellView supports extra view modes, they'd be there. Similarly, those which should be disabled would be, since it would all be under the IShellView's control).
I have read Raymond Chen's excellent How to host an IContextMenu. Unfortunately, that just gives me a very simplistic context menu - the one for the folder itself, or for a file in a given folder, but NOT the context menu for the IShellView's shell view window (from which I might obtain the view fly-out).
I have tried the following, based on Chen's article:
CComQIPtr<IContextMenu> pcm(m_shell_view); // <<-- FAIL resulting pointer is NULL <<<
// create a blank menu
CMenu menu;
if (!menu.CreatePopupMenu())
throw CContextException("Unable to create an empty menu in which to store the context menu: ");
// obtain the full popup menu we need
if (FAILED(m_hresult = pcm->QueryContextMenu(menu, 0, SCRATCH_QCM_FIRST, SCRATCH_QCM_LAST, CMF_NORMAL)))
throw CLabeledException("Unable to query the context menu for the current folder");
// display the menu to the user
// menu.getsubmenu
::TrackPopupMenu(menu, ::GetSystemMetrics(SM_MENUDROPALIGNMENT)|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, m_shell_view_hwnd, NULL);
Unfortunately, the attempt to query the m_shell_view (which is an IShellView*) for its IContextMenu interface fails. This "works":
// retrieve our current folder's PIDL
PidlUtils::Pidl pidl(m_folder);
// get the context menu for the current folder
CComPtr<IContextMenu> pcm;
if (FAILED(m_hresult = GetUIObjectOf(m_owner->m_hWnd, pidl, IID_PPV_ARGS(&pcm))))
throw CLabeledException("Unable to obtain the PIDL for the current folder");
But here I get only a very few options in the context menu (Open, Explore, ...). Not the detailed context menu that I get if I simply right click on the shell view itself.
I'm out of ideas as to how to proceed. Help?! ;)
Try IShellView::GetItemObject with SVGIO_BACKGROUND as uItem to get a IContextMenu on the view object : http://msdn.microsoft.com/en-us/library/bb774832%28VS.85%29.aspx
There is the SHCreateDefaultContextMenu (Vista an up) that may be of help. Bjarke Viksoe website contains great info as well.
SVGIO_BACKGROUND will get you the background context menu of the shell view. You may need to call repeatedly pShellView->SelectItem for each PIDL you may have, then do the GetUIObjectOf call (then QI for IContextMenu, create a menu, call IContextMenu(3)::QueryContextMenu and finally display it with TrackPopupMenu).