How to hide/collapse main menu in a win32/mfc application - c++

I always been interested on how we can accomplish this (hide/show the main menu using the alt key), and now some applications do this very often. One that really please me is the visual studio 2010 with this plugin:
http://visualstudiogallery.msdn.microsoft.com/bdbcffca-32a6-4034-8e89-c31b86ad4813?SRC=VSIDE
(firefox also do this, but i think that is in a different way)
Can anyone explain me how this can be achieved or if you known of any sample project that demonstrate this please tell me.
(what i can see in some replies here in stack is that we have to destroy the menu when is to hide and create it when is to show?! but this seems a bit bad solution...)
Thanks

The SetMenu function lets you add/remove the menu from the window. It does not destroy the menu.
Note that most applications which have the dynamic menu hide/show behavior are not really showing a menu. They're showing a custom control that looks like a menu.

You might also take a look at MFC support for auto hiding menus. I used this technique and it worked really well.

in CMainFrame::OnCreate I did
m_wndMenuBar.ShowWindow(SW_HIDE);
which actually works fine in our project

I stumbled across a related pit fall that will show a hidden main frame without your consent:
Whenever the focus for a child window in an MDI application changes (e.g. due to right clicking in it), the function CMDIChildWnd::OnMDIActivate will be called, which in turn shows the main menu (even if it was removed or destroyed previously) of the MDI application.
This works basically by adding the saved main manu from the underlying's CMDIChildWnd m_hMenuShared variable.
A quick&dirty hack to prevent this, is setting m_hMenuShared to NULL (it's protected in CMDIChildWnd so this needs a custom derived child class of CMDIChildWnd) for all child frames.

Related

CMFCMenuBar and TestStack.White win.MenuBar is null

I'm trying to use TestStack.White to Automated an MFC Application (for UI testing purposes)
When using TestStack.White with an MFC Application written with CMFCMenuBar (the later Docking framework MFC) I noticed that code like the following fails due to window.MenuBar being null
var menu = window.MenuBar.MenuItem("Window");
menu.Click();
I know I can overcome this issue with the following
TestStack.White.UIItems.MenuItems.Menu windowMenu = win.Get<TestStack.White.UIItems.MenuItems.Menu(SearchCriteria.ByText("Window"));
windowMenu.Click();
But what I really want to do is get the ChildMenus so that I can check the list of windows open in the window menu, but the windowMenu.ChildMenus is empty
I am pretty sure this is because the menu is really a toolbar/toolstrip (dockable)
Does anyone know how to get the menu items (Tile,Cascale,Window1....) from the Window Menu
Has anyone else seen this issue or found a work around?
Thanks in advance
Paul
Yes, the MFC feature pack menu is really a toolbar with buttons. And it is fulfilled using a different process compared to the old style menu.
In your CFrameWndEx derived class, for getting the menu bar you can do:
CMFCMenuBar *pMenuBar= m_Impl.GetMenuBar();
Then it depends on what to do with it. For example, if you want to get the CMenu object that constitutes the menu bar you can do:
CMenu* pMenu= pMenuBar->GetMenu();
If you want to remove some of the menus, you can do (Notice the reverse order):
pMenuBar->RemoveButton(4);
pMenuBar->RemoveButton(3);
You can not get the menu the typical way by YourCFrameWndExDerivedClass::GetMenu() because these new MFC Feature Pack classes intentionally do SetMenu(NULL) when initializing the main frame, as you can see in the call stack:
I am not absolutely sure, but I think you won't also be able to do the override YourCFrameWndExDerivedClass::OnInitMenu() as you could in the old style menus. But you can still use the YourCFrameWndExDerivedClass::OnInitMenuPopup() overrride.

Creating a DialogBar with MFC with my own controls

I'm turning mad with a little problem with Visual Studio 2008 and MFC. I'm working on a project actually and I'm trying to create an SDI Application. Right, now I want to add a dockable DialogBar. Well, the first time I added it with the resource view, I could create the bar without problems.
But... I want to add some controls like a couple of ListBox, buttons and so on. The program doesn't allows me to create member variables for these controls. The option appears in grey.
Searching a little, I found that it's mandatory to create a new class derived from CDialogBar and "enhance" it with the Message handler and so on. I've been reading some tutorials and it didn't work for me.
Can you please help me? I'm starting to get nervous, the use of dialogbars is mandatory in my design and I've never implemented them before.
Thank you very much, and sorry for my poor english.
You can add a control member variable by hand instead of using the wizard. All it takes is a call to DDX_Control in the dialog bar's DoDataExchange function.
But CDialogBar-derived classes do not handle control clicks. The CDialogBar class forwards all of those messages to the dialog bar's parent window. So be prepared to add the message handlers to the parent (usually CMainFrame).
For learning purposes you might try creating your dialog bar as a CDialog first, to see the proper code lines and message map entries supplied by the wizard. Then you can copy/move these details as appropriate into your actual code project.

Is it possible to change the location of the main top-level menu in an MFC MDI app?

I have an app with a customized frame (i.e., caption/titlebar, borders). I customized the frame by removing the WS_CAPTION style, and overriding OnNcCalcSize to reserve a custom-sized area for the caption, which the app paints in OnNcPaint.
A side effect is that the menu bar no longer displays, which is OK because I want to customize the appearance & location of the main menu. Unfortunately, I don't know how to do that. I would like the "File" menu to be further from the left edge than it is with the standard menu bar.
An acceptable alternative would be to remove the menu entirely, and use OnNcHitTest, OnNcPaint and OnNcMouseMove to manage a hand-coded replacement for the top-level menu.
I've never seen a way to modify the looks of the standard menu. You can remove it (remove the creation code from your InitInstance) and then code a replacement. I wouldn't do that in OnNcXXX though, rather make a new custom control that you position at the top. Or you could have a look at the MFC Next themed menus and write a custom UI renderer. It may be enough to override a few functions left and ride to set the alignment of the menu.
It's an MFC MDI app -- InitInstance is not where the menu is being created. I have tried to get rid of the menu (and succeeded, temporarily) but the MFC framework seems to be "putting it back" -- I think the MDI model has the child windows modify the menu, but the code that does that seems to be buried in the framework somewhere (or else I just haven't been able to find exactly where it happens in the application's code, but I suspect it's happening inside the MFC framework code). If I knew where, I might be able to override the methods(s) and take control... I think.
What would be the reason to write a custom control vs. handling OnNcMouseMove & OnNcLeftButtonDown, e.g.? I don't expect to need the functionality in any other app (a new app would be coded in C#, probably), so I'm looking for ease of implementation, not code reuse.

How to mix C++ and external buttons on seperate window?

I want to make a C++ button on Start>Run i.e but when I do it will not do signalled event?
Im sorry I have seen that you do not get the question.
Ok basically when you create a button with CreateWindowEx(); I want to do that but put on a different window with SetPArent which I have already done now the button does not work so I need my program to someone get when it is clicked from the Run window as example!
And yes you have it, but it's not making the button is the problem it's getting when it's clicked with my program since it does not belong to it anymore!
You need to apply the ancient but still-supported technique known in Windows as subclassing; it is well explained here (15-years-old article, but still quite valid;-). As this article puts it,
Subclassing is a technique that allows
an application to intercept messages
destined for another window. An
application can augment, monitor, or
modify the default behavior of a
window by intercepting messages meant
for another window.
You'll want "instance subclassing", since you're interested only in a single window (either your new button, or, the one you've SetParented your new button to); if you decide to subclass a window belonging to another process, you'll also need to use the injection techniques explained in the article, such as, injecting your DLL into system processes and watching over events with a WH_CBT hook, and the like. But I think you could keep the button in your own process even though you're SetParenting it to a window belonging to a different process, in which case you can do your instance subclassing entirely within your own process, which is much simpler if feasible.
"Superclassing" is an alternative to "subclassing", also explained in the article, but doesn't seem to offer that many advantages when compared to instance subclassing (though it may compared with global subclassing... but, that's not what you need here anyway).
You'll find other interesting articles on such topics here, here, and here (developing a big, rich C++ library for subclassing -- but, also showing a simpler approach based on hooks which you might prefer). Each article has a pretty difference stance and code examples, so I think that having many to look at may help you find the right mindset and code for your specific needs!
OK, I'll do my very best - as I understand you, you're trying to inject a button into some existing window. That meaning: Your tool creates a button in some window that does not belong to your application. Now, you want to be notified when that button is pressed. Am I correct so far?
To be notified about the button being pressed, you need to get the respective window message, which will only work if you also "inject" a different WndProc into the window. Actually I have no idea how that should work, but I faintly remember functions like GetWindowLong and SetWindowLong. Maybe they will help?
EDIT
I've searched MSDN a little: While you can get the address of a window's WndProc using GetWindowLong, you can not set the WndProc using SetWindowLong on Windows NT/2000/XP (and up I suppose). See here (MSDN).
So what you could do is install a global message hook that intercepts all window messages, filter those for the window you've injected the button into and then find your message. If you have trouble with this, however, I'm the wrong person to ask, because it's been years ago since I've done anything like that, but it would be stuff for a new question.
EDIT 2
Please see Alex Martinellis answer for how to define the hook. I think he's describing the technique I was referring to when I talked about defining global message hooks to intercept the window messages for the window you injected your button into.

How to get the minimize and maximize buttons to appear on a wxDialog object

I've run into an issue using a wxDialog object on Linux In the construtor for the object I pass the relevant style flags (wxCAPTION|wxMINIMIZE_BOX|wxMAXIMIZE_BOX|wxCLOSE_BOX|wx_RESIZE_BORDER) but the buttons don't show up. When I was designing the class in wxformbuilder they would appear on the displayed design but don't show up in my running application.
I'm using wxWidgets 2.8.7 at the moment and running on Scientific Linux 5 (RHEL 5). Any suggestions or ideas on how to work around this?
EDIT: BTW, This is related to this question
If you create a dialog on wxGTK then during construction
gtk_window_set_type_hint(GTK_WINDOW(m_widget), GDK_WINDOW_TYPE_HINT_DIALOG);
is called, which leaves it up to the window manager what decoration is shown for this window. So if you give it the style but no buttons are shown, then there's nothing you can do. In any case, I think showing a wxFrame while the parent frame is disabled should work just as well.
Can you use a wxWindow instead of a wxDialog? Maybe it doesn't make sense to minimize a dialog but those are usual operations for application windows.