Find menu item based on mouse position in C++ - c++

I am trying to get the menu item from another application.
I can do this by manually getting the handle to the main menu and loop through its sub menu. But it is very difficult to find out how many levels of sub menus are there for a given menu. For example if we look at outlook view menu some thing like this, View -> Arrange by -> Current View -> Messages.
So i decided to get the menu item based on mouse position. But i cant find a way to do that.
Please suggest some idea to do this.

I suspect that what you're trying to achieve is more or less made impossible by how the menu system in windows is designed.
Note that there might be some non-conventional ways around this, however I doubt you'll find such a solution to carry less amount of work than your current strategy of traversing the menu hierarchy.
The thing is, a hierarchy of menus and submenus is actually a tree of regular menus. In MFC you have a tree of CMenu objects and in the win32 C api it's a tree of HMENU handles.
Each menu, regardless if it's a submenu or main menu, have a number of items which by themselves are not objects. I.e. there's no MFC class called CMenuItem and no win32 API handle type called HMENUITEM. If you look at any function dealing with menus, it's always about passing an ID of a menu item. For instance look at CMenu::EnableMenuItem or CMenu::GetDefaultItem.
Now, the real problem is comprised of two facts - Menu items are local to the menu they're located in. If you look at any function in the C API, you always need to specify both menu handle and menu item ID, due to the fact that item IDs can't be resolved unless the framework knows which menu object you're talking about. Hence IDs are not global. In MFC you usually don't need to specify the menu handle, but that's ofcourse because the CMenu object itself wraps the HMENU handle.
The second part of the problem is that there's no natural way of retrieving a menu (CMenu or HMENU) from position. You can get a menu item from position through MenuItemFromPoint, but as you can see you also need the menu handle and the returned ID is only valid in combination with the menu handle you specify. Since you can't get that menu handle any other way than traversing the submenu hierarchy - you're back to square one.
As a final note - the capabilities of Visual C++ menus (CMenu) are always limited to the capabilities of the Win32 C API menu functions, so any functionality not found there is more or less out of reach.

Related

How insert multiple FormView in View of an SDI application

I searched on the forum and I don't find a solution for my issue. So I hope you can help me :)
I work on a personal project for SFC designing (Sequential functional chart) and I'm working with visual studio in SDI(I'm using MFC library). If you see the "design" of an SFC you can see the different elements needed to compose this. So you can find Step, Transition, and more. If I take a step for explaining my issue, after double click on the step a popup dialog is opened with the elements to define this step (actions on this step, and more). The issue is here, I can't see two or more step elements at the same time. I want to reuse the existing concept on other software, see this.
Step close
Step open
Dialog to add
My question is, how I can implement a dialog with my graphic element in mainframe (In this case, a step)? I don't know how I can insert a dialog with my element, I think I need to use CFormView, but I don't know.
This dialog needs to be resizable and reduce directly by the step graphic.
any idea?
Thank you in advance! Sorry for my English ..
Sorry, I think my request is not clear .. (Thank you for your answer)
The context, it's an SDI application with the Document/View architecture. Actually the view is derived from CScrollView.
So, in the document class, you have the different lists of components for make SFC (Steps, transitions and symbols ..). I'm working today on Step element.
The user inserts a new step, the step is draw on the view like this :
enter image description here
And now the user want change the events on this Step, for this after double click on the step the events editor is opened at right of step draw, like this :
enter image description here
For this, I've created a new dialog resource and create the class by wizard in CForwView derived class. In step attribute, you can find one instance of this derived class (The derived class of dialog).
But this doesn't work correctly, I think my method is bad. At the first try, I have sent the pointer of the current document to the "CFormView::Create" function for having the "Save" button active with the focus on the FormView. But after destroying the step, the instance of FormView is destroyed and the document with the instance of formview ...
No problem, you can use "Create" within CCreateContext a null pointer. But with the document or without I have a lot of problems (graphic design not correct in FormView, regularly (not systematic I have assert fail on Proc exchange (for differents reason)). But the "concept" is good, the editor follows the draw if I scroll, I can open or close the editor at any time and on any elements.
For the old capture, it's my SFC designer "model". My application is a complement to this application, so I want a similar design. I don't know how work my model application ..
On my application all is draw by MFC GDI, I don't use ActiveX or other tools.
So what is the correct way to implement one instance of editor by instance of step ?
For the implementation on this FormView I have :
- Make new dialog in ressource
- Create a derived class of CFormView with the created dialog
- Add one instance in attributes of Step element
- "OnDbClickOnStep" -> Call "Create" with the good position / size, pointer of mainview (in my case the CSrollView derived class)
- Done, FormView inserted in a mainview, I can edit my step events.
? Not done, I lost save button and other function linked to the document with the focus on a control in FormView. The app want a document with this view, how to override this ?
? Error in Proc exchange, for different reason...
You have an idea ?
You normally don't draw anything in the "main frame" (or the "MDI clild frames", in the case of a MDI application), this is done by the library, and imo sufficiently so. You display your data in a CView-derived class.
CView is the base class of all other MFC view classes. It's a simple graphical class - you need to paint it yourself in the OnDraw() member.
CScrollView is a descendant of CView, adding scrolling functionality (scroll-bars are automatically displayed if the scrollable area is bigger than the visible window area).
CFormView is a descendant of CScrollView, displaying a dialog resource-script, containing "controls" (edit-boxes, check-boxes, images, ActiveX etc).
As in your case the "controls" won't be initially known (except maybe for some few special cases) and rather programatically created, the resource script will most likely be empty, so using either CFormView or CScrollView will basically be the same. I would suggest starting with CFormView, and "downgrade" it to CScrollView if CFormView is not necessary or causes you troubles.
What are those "Step" items shown in the pics? ActiveX controls, child dialogs maybe? These work best as child controls on a dialog window. Are they already implemented, or they are just pics of some other software? Btw ActiveX is a way to define controls that can be used in other projects too, without having to include them in the project source.

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.

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.

Extend an external application's menu

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.

How to show available windows in the Window menu

I have a MFC MDI application that I've recently ported from VS2003 to VS2008, and at the same time moved from Stingray Objective Studio 2006 v2 to v10.1. On the previous versions of my application, if I had more than one view open, the Window menu would be populated by an enumerated list of available views, e.g. 1 MyViewA, 2 MyViewB etc... If I had a large number of views, I would also get a Windows... menu option to allow me to select a view. This no longer happens, which is breaking some of my GUI level regression tests. My guess is that this functionality was implemented by either CMDIFrameWnd or SECMDIFrameWnd but I couldn't find a reference to it in the documentation. Does anyone know how I can get this functionality back.
First thing I'd do is create a new MDI application with the ClassWizard and check if the functionality you're missing is present. If so, poke around and see if you can tell what's different. One place to look may be the menu resource for the main menu.
If there is no in-built functionality to provide what you need, you can dynamically build the menu with the following pseudocode:
foreach registered CDocumentTemplate
foreach document
foreach view
{
if (numberOfWindowMenuItems < 5)
{
Add menu item
}
else
{
Add "Windows..." menu item
break all loops;
}