Is there a way to change the position of the popup menu. With top-level windows I can do it by CBTProc Callback Function and MoveWindow. Can I do the same with menus? Needs to be done so that the pop-up menu is located only in the area of its parent window. Something like a light window manager.
Yes, in a WH_CBT hook callback, you'll be notified with an 'nCode' of HCBT_CREATEWND whenever a menu window is created. Test for the class name, standard menu/submenu windows would have a class name of '#32768'. You can then send a MN_GETHMENU message to the window to find out which menu is about to be activated. But as documented, it is too early to move the window when the notification is received, the menu is not even visible yet, so you might need to sub-class the window and process additional messages.
Note that you don't need a hook to be notified when a menu window is shown, you can put a handler for the WM_ENTERIDLE message, test for 'wParam' to see if a menu caused the message, get the menu window from 'lParam' and again send a 'MN_GETHMENU' to find out the specific menu. It is possible to move the window at this point without further message handling. Just be aware that 'WM_ENTERIDLE' will be called multiple times so you need to keep track of you've already moved a particular window or not.
Related
I have an application with a tray menu and I'm trying to automate some tests that involve the tray menu. Basically I need obtain the tray menu's items and do stuff with them.
However, I've only been able to find ways to programmatically obtain menu items for within the application. But my automation tests are going to be an external application, so that doesn't help me.
How can I obtain an external application's tray menu items programmatically?
There are ways to enumerate/access the tray icons themselves (usually involving hooking into the notification tray itself, or using UI Automation), but there is no way to access a popup menu that appears when a tray icon is clicked on. The reason is because the icon's owning application receives a message when the click occurs and then acts accordingly, which usually involves displaying its own popup menu. There is no menu associated with the icon itself.
For what you are attempting, you would have to enumerate the icons and figure out which icon belongs to the app you are interested in (not a trivial task on its own), then simulate a click on the icon so the app displays its popup menu. See the following question for some details:
Finding and simulating a click on a system tray icon?
Interacting with the popup menu once it is displayed will be more difficult. You won't have access to the menu itself. You will likely have to resort to just issuing mouse events via mouse_event() or SendInput() to move the mouse cursor over the menu and click its items (assuming they appear in predictable locations relative to the icon).
If you can obtain the icon's HWND+ID or GUID (by hooking the notification tray itself), you can use Shell_NotifyIconGetRect() to get the icon's coordinates, at least.
How can I obtain an external application's tray menu items programmatically?
You cannot. There is no public API that provides access to notification icons.
Depending on what sort of assumptions you find acceptable, you can programmatically interact with the taskbar button's menu once it's visible. The image below shows the Inspect SDK tool reporting properties on the OneNote clipping tool button's menu. (And the menu items say they support the UIA Invoke Patten, so they should be programmatically invokable by UIA client code.)
If you want to invoke your tray button's menu items, you might consider the following steps using UIA. You may feel the assumptions that I make here are unacceptable for your situation.
Find the element with a class name "NotifyIconOverflowWindow", that's a direct child of the root menu. I'm assuming the button is in the overflow area.
Enumerate the children of the overflow element, looking for a button with the name of your button. This assumes the UI language is known and accounted for.
Get the bounding rect of the button and simulate a mouse right-click on the button. The click simulation is necessary because I'll bet the UI doesn't support IUIAutomationElement3::ShowContextMenu(), (but you could always try it).
Once the context menu's up, find the element with a ControlType a Menu, a Name of "Context", that's a direct child of the root element.
Once you have the menu, enumerate the child elements in the menu to find the items, and do what you want with them. Eg get the menu item's Invoke pattern and invoke it.
I've been researching popup menus (see https://msdn.microsoft.com/en-us/library/windows/desktop/ms647626(v=vs.85).aspx) and a bit confused at what they are behind the scenes.
They act partially like windows, but look like controls. For instance, they pop up above other elements, steal focus, and can go outside their parent container which makes me think they are a type of window. But they pass back an HMENU handle instead of a window handle, and they have no title bar, nor handles, nor show up in the task bar.
If they are a type of control, how can they go outside their parent window?
If they are a type of window, can I use window-specific functions on them? or if they are a control in a new window, is there a way to get a win handle to that new window?
Can I get the location of the popup menu for another application?
Found the answer:
trying to get a handle to a context menu in c++
Looks like a menu is a type of window, that is a child of the desktop window. You can get its window handle with EnumChildWindows on the desktop WinHandle and look for the class name of #32768.
There's more about these reserved system windows here:
About Window Classes | System Classes
A popup menu is a menu, not a window.
A menu merely uses a window for display. A new window is created each time the menu is displayed, and is destroyed afterward. By contrast, the same HMENU can be used to display the menu many times.
I have a desktop application written in Ruby that is using GTK2. It's just a small test application to play with GTK2, but I'm having problems achieving what I want to do. Is there any way using GTK2 to get at the titlebar (apart from setting the title), specifically to either add a button to it (beside the min/max/etc, B in the below diagram) or to add an option to the menu that pops up when you click the icon on the titlebar (A in the below diagram)?
I'm thinking there might not be because GTK is meant to work with many many different window managers, but I just wondered if there was. As a side question, what event does clicking the 'cross' button fire? At the moment if the user clicks that the window disappears but the program doesn't end - I need to capture that event and quit the program.
Thanks for any help, including hitting me over the head and telling me how silly I am.
Note that this is possible in GTK 3.10 and up, by using gtk_window_set_titlebar(). It replaces the window manager's title bar with a custom one. GtkHeaderBar is a good custom title bar class to use.
You can't, however, make it look just like the window manager would, because you won't know which window manager the user is running.
No, the title bar is owned by the window manager and you will typically not have direct access to it.
When the user tries to close the window by clicking the window manager's button, the window will receive the delete event.
Normally when creating a sub window (WS_POPUP), the child window will become activate and the parent will become deactivated. However, with menus, both remain active. At least I am assuming the menu is active, it at least has focus.
Example: Click on the file menu in notepad, the menu appears, yet the notepad window still looks active.
Is it possible to mirror this behavior with either a window style or responding to a particular message?
Thanks
Another example: Combo boxes seem to show a subwindow, yet do not deactivate the window. And you can click on that subwindow, while still maintaining an activate main window. Any ideas on how to grab the class /style of that window?
The list dropdown in a combobox is a bit of a hack, it is both a popup and a child window, I can't recommend that approach (Undocumented style combination, and IIRC, it is a bit buggy to do this with a "normal" floating window/toolbar)
This leaves you with two options:
WS_EX_NOACTIVATE (Main window will stay active, floating window is not active)
Handle activate messages (Both windows will look active)
I am surprised that creating a new popup window activates it. Normally you'd need to call SetActiveWindow. However check out WM_ACTIVATE and WM_NCACTIVATE on how to stop the window becoming deactivated.
A fact that a lot of people miss is that windows does not have a separate window manager component :- most of the window management duties are performed by each window - usually in DefWindowProc.
Most window positioning and activation / de-activation is done - ultimately - via a call to SetWindowPos - which always sends a WM_WINDOWPOSCHANGING message allowing the window to have a final say on what happens.
DefWindowProc also activate its own window in response to mouse clicks and so on.
The result of all this is, it is quite possible to create windows that never accept activation - it does require an extensive understanding of what messages and situations might have led to an activation.
Ultimately I can say that it is VERY handy to have a debugging setup configured for remote debugging - so that you can interact with your debugger without effecting the activation state of the system - and hence drop a breakpoint into the window in questions WM_ACTIVATE handler and simply debug any situation leading to an unwanted activation.
If You want to handle keyboard focus as well, it might be trickier - normally focus is given to an activated window - but again its usually the DefWindowProc responsible for assigning both. I just see it dangerous as having one window, still obviously activated, and another with focus. This will confuse any assistive software greatly.
I'd be tempted to perform a message loop level message hook - Similar to IsDialogMessage - to filter keystrokes intended for the popup window.
If you create your popup window with WS_EX_NOACTIVATE it will not be activated by user input (You could still activate it programatically) and therefore your main application window will still remain active.
I write a MFC application and need a button which is not taling the input focus away from another window.
Removing the WS_TABSTOP style does unfortunately not help when the use clicks the button with the mouse. When i block WM_LBUTTONDOWN i don't get a visual pressed indication so this doesn't work either.
If there is a specific window you want to keep the focus, you could just force the focus back to your window using the CWnd::SetFocus() command in your button's OnLButtonDown handler.
If you want the focus restored to one of several windows, you could try subclassing CButton and trapping the CWnd::OnSetFocus() message which is sent when the keyboard focus changes to the button.
The OnSetFocus() event includes a CWnd of the control that just lost the focus, so you could manually put it back, either as part of the OnSetFocus() event itself, or later as part of the OnLButtonDown() handler again.