C++ - MFC - Change text of a CMenu - c++

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.

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.

C++ Set window below (or above) the icons on the desktop

I'm trying to place a window either above or below the icons on the desktop. I mostly just want it to stay attached to the desktop at all times. Similar to Rainmeter or Wallpaper engine. So far, everything I tried either disables interaction, or gets minimized when you use the "Show Desktop" button. Any ideas on how to achieve this? I'm using electron and a native module in node to do this.
It's an old subject, but I'll find out how to do it recently and answer it.
The method is to find the handle of SHELLDLL_DefView, the parent of the desktop window, and then make the SHELLDLL_DefView handle the parent of my window to fix it to the desktop.
The method is to find the handle of SHELLDLL_DefView, the owner of the desktop window, and then make the SHELLDLL_DefView handle the owner of my window to fix it to the desktop.
SHELLDLL_DefView is located under the Progma or WorkerW handle. This is a code to prevent ShowDesktop from being used in the Electget package created by ffi-napi to attach the Electron browserWindow to the desktop.
const GWLP_HWNDPARENT = -8;
// find SHELLDLL_DefView in Progma
const progman = user32.FindWindowExA(ref.NULL, ref.NULL, 'Progman', ref.NULL);
let defView = user32.FindWindowExA(progman, ref.NULL, 'SHELLDLL_DefView', ref.NULL );
// find SHELLDLL_DefView in WorkerW
if (!defView) {
const desktopHWnd = user32.GetDesktopWindow();
let workerW = 0;
do {
workerW = user32.FindWindowExA(desktopHWnd, workerW, 'WorkerW', ref.NULL);
defView = user32.FindWindowExA(workerW, ref.NULL, 'SHELLDLL_DefView', ref.NULL );
} while (!defView && workerW);
}
if (!defView) return false;
// make the SHELLDLL_DefView handle the parent of my window
user32.SetWindowLongPtrA(hWnd, GWLP_HWNDPARENT, defView);
This allows you to create a window where you can click and interact without being hidden by ShowDesktop.
2022-03-29
There was a wrong word, so I corrected it. According to doc, it is not a parent window, but an owner window. In the doc, it is strange that the GWLP_HWNDPARENT constant is related to the parent window. However, when tested with Spy++, the corresponding constant changes the owner window.

Problems with CMenu::ModifyMenu

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...

How can I disable and gray the top level menu item using MFC

I have a dialog application in which I want to have clickable menu items at the top of the dialog. These items do not show a drop down menu but actually run the associated commands.
I did this by setting Popup=False in the dialogs properties and assigning a message-id but my problem is not having the ability to disable the item properly when it makes no sense for the item to be clickable (depending on internal state stored in the dialog)
I have already found out how to disable any popup-parent menu items from http://www.microsoft.com/msj/0299/c/c0299.aspx, but this isn't exactly what I want
I have also found out how to add menu command routing to dialogs from the msdn knowledgebase article KB242577.
This works fine for sub-menu items, but not for the top level menu.
I am currently using the following function to do the disabling
void CYourDlg::EnableMenuItem(UINT nCommand, BOOL bEnable)
{
CMenu* pMenu = GetMenu();
pMenu->EnableMenuItem(nCommand, bEnable ? 0 : MF_DISABLED | MF_GRAYED);
}
This half works, if you alt-tab away from the app it does show as disabled, otherwise it doesn't.
Is there a way to invalidate the area programmatically?
I think an non-client area message may be involved.
I have not tried but in regular window (not dialog) CWnd::DrawMenuBar should do what you want. It might work with dialog based applications as well.
void CYourDlg::EnableMenuItem(UINT nCommand, BOOL bEnable)
{
CMenu* pMenu = GetMenu();
pMenu->EnableMenuItem(nCommand, bEnable ? 0 : MF_DISABLED | MF_GRAYED);
DrawMenuBar();
}
I think you should add an ON_UPDATE handler for your menu ID. This would ensure that the menu is enabled/disabled when you want to.

How do I display a tooltip for a CMFCRibbonButton in the status bar?

I have a CMFCRibbonStatusBar in my mainframe to which I add a CMFCRibbonButtonsGroup which again has a CMFCRibbonButton. This button has the same ID as a menu entry.
Creating the button is done as follows:
CMFCRibbonButtonsGroup* pBGroup = new CMFCRibbonButtonsGroup();
CMFCToolBarImages images;
images.SetImageSize(CSize(32, 16)); // Non-square bitmaps
if(images.Load(IDB_STATUSBAR_IMAGES))
{
pBGroup->SetImages(&images, NULL, NULL);
}
m_pStatusButton = new CMFCRibbonButton(ID_STATUS_SHOWSTATUS,
_T(""),
IMAGEINDEX_DEFAULTSTATUS);
pBGroup->AddButton(m_pStatusButton);
m_wndStatusBar.AddExtendedElement(pBGroup, _T(""));
I want to use this button as a status indicator.
I want to display a tool tip in the following two cases:
when the status changes and
when the user moves the mouse over the button.
I have no idea how to start in the first place. I have looked at the ToolTipDemo and DlgToolTips sample projects but couldn't figure out how to do it since all they do is display tooltips for the toolbar items or dialog buttons (CWnd-derived instead of CMFCRibbonButton).
If you are familiar with the ToolTipDemo sample project: Since there seem to be several ways of doing things, I would prefer the tooltip to look like the "Extended Visual Manager-based" tool tip as shown in this screenshot.
Thanks!
I don't think it's possible to show the tooltip without the mouse cursor being over the control. That's all done automatically.
However if you want to have a nice looking tooltip like in your screenshot, you need to call SetToolTipText and SetDescription, like this:
CMFCRibbonButton* pBtn = new CMFCRibbonButton(12345, _T(""), 1);
pBtn->SetToolTipText("This is the bold Title");
pBtn->SetDescription("This is the not-so-bold Description");
pGroup->AddButton(pBtn);
I am using CMFCRibbonButton controls within a CMFCRibbonButtonGroup, which is added to the CMFCRibbonStatusBar. Take note of the 4th parameter in the CMFCRibbonButton() constructor, bAlwaysShowDescription, as this seems to affect the behavior depending upon whether SetDescription() has been called.
Specifically, if SetDescription() has not been called, it doesn't matter whether bAlwaysShowDescription is TRUE or FALSE - the tool tip is displayed (as I would expect). If SetDescription() is set and bAlwaysShowDescription is FALSE, when hovering over the button the tool tip is displayed with the description below it.
What seems counterintuitive given the name of this bAlwaysShowDescription parameter, is that when this is TRUE and SetDescription() is set, NEITHER the tool tip nor the description appear. I wonder if this is related to this post:
https://connect.microsoft.com/VisualStudio/feedback/details/399646/cmfcribbonbutton-wont-show-tooltip-if-balwaysshowdescription-1
Hope this helps and you can achieve what you need with the different combinations of bAlwaysShowDescription parameter and whether SetDescription() is set.