Extend an external application's menu - c++

I am currently writing a plugin for a third party application.
As the plugin framework does not provide any way to access the UI I am now trying to do this manually via the WinAPI.
More specifically, I want to add a custom menu item for my plugin in the "File" menu.
My first attempt using FindWindow to retrieve the handle of the main window and the using GetMenu was not successful, as GetMenu simply returned NULL.
My next step was to use EnumChildWindows and search for a child having the text "&File" (I really don't like this approach as it makes localization quite terrible). However, I only found out the handle of the menu item, but I need the corresponding HMENU to use AppendMenu then, don't I?
Simply casting does not work and results in an "Invalid menu handle".
Is it actually possible to achieve what I am trying? How?
Thanks for your ideas in advance!

It more than likely just isn't a HMENU. Custom menu implementations are common, the one Window provides is dated and inflexible. Compare to Windows Forms' MenuStrip for example.
Of course, that blows a gaping hole in your approach.

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.

Accessing a right click context menu from an external application

After performing some Google-fu and searching Stack Overflow I've been unable to find a way to access the right click menu of an item and read data or select an item from it. I've looked up methods for SendMessage and PostMessage
What I've done so far:
This is an example of post here that would have been exactly what I want if it didn't use Qt and would work on an external application. Everything I've been able to find is about creating a right click menu when I just want to view an external application's right click menu.
I've tried getting the handle of the context menu using Spy++ but the menu just disappears as soon as I select the "Find Window" option in Spy++ (which is to be expected).
The only way I could think of doing this is using mouse_event to display the box but then I don't know where to go from there. I feel like this would also be very inefficient.
I'm working on some legacy code so I don't have a lot of choice in what I can use, if it's possible I'd like to not use libraries that aren't included in Visual Studio 2008.
What I'm trying to do:
I'm looking for a way to access the right click context menu in an external application and read the data in it and then select an item. I feel like this should be really simple but my research skills are subpar. If anyone can point me in the right direction I would really appreciate it.
Thank you for reading!
The only way you can get hold of a context menu is to make the application display it. It doesn't exist otherwise. (The other question you give as an example is regarding the Windows Shell menu which is designed to be useable)
A window gets sent WM_CONTEXTMENU when the user right clicks, so you could use SendMessage() to invoke the menu, or failing that just send a right click.
After a bit of googling, I think context menus have a classname of #32768, so you could use FindWindowEx to find a child window handle with the matching classname.
Once you have the window handle, you can use the MN_GETHMENU message to get hold of the menu handle.

using SHAutoComplete with CEdit control

I am developing an MFC application, can i use SHAutoComplete with a CEdit control? Also is there any ready made auto complete controls are available? or i need to use write all the code for creating the list box below the edit control as user types in edit control?
Just pass CEdit's m_hwnd member to SHAutoComplete. I don't think that extension warrant another class. The listbox is created by the AutoComplete object created by SHAutoComplete.
SHAutoComplete helps to autocomplete paths (system or URL).
If this is a combo box and you want to use autocomplete for suggesting string contained in the combo, you have to write a code to handle it.
There are samples you can find. One I found (working):
http://www.ucancode.net/Visual_C_MFC_COM_faq/Visual-C-Auto-completion-ComboBox-CComboBox.htm

Retrieving Menu in Explorer

As the context menu for the desktop and explorer windows is disabled, I wanted to make a little something to bring back some functionality. My idea was to just list out things in a context menu (copy, paste, new, open with, etc) whenever a user right-clicks one of these windows, and then just simulate the appropriate event in the actual menu (file->new, edit->copy, etc). It wouldn't look perfectly pretty, but it would hopefully allow for the use of right-clicking.
The problem is that I cannot seem to get the actual menu. I opened My Documents and tried going down the child list towards SysListView32, calling GetMenuItemCount each time. Most returned -1, and the only other return value than that was 0.
How am I supposed to get a handle to the (file, edit, view...) menu?
If this isn't possible, is there a way I could simulate the user clicking something on the normal context menu, even if it's disabled?
Also, is there a way of making this work for the desktop? You can get the same type of thing if you view it in the explorer window, so I figured there might be a way.
I'm running Windows XP and any help is appreciated.
As per David Heffernan's comment,
As for your question, you are on the wrong track.
GetMenuItemCount needs an HMENU but you've been feeding it HWND.
That won't work. It also won't work from a different process.
You could possibly write a program that use the shell COM APIs
to show a context menu for a shell item. But your basic problem
is the bone-headed group policy. You really need to get that fixed.
Tell the IT guy that takes the decision that I said he was a fool
and was stopping you doing any useful work. ;-)
This led me onto the path of using the correct alternative method to achieve my goal.

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.