What type of Resource is a Popup Menu in Windows? - windows

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.

Related

How to set title/caption of Scintilla window

I have created a Scintilla window using CreateWindow() and want to set the title dynamically as different files are loaded into it. However, SetWindowText() is setting the content of the edit box rather than the caption. I also tried WM_SETTEXT to the same effect.
How do I set the title of the window instead?
Is the Scintilla window a top-level window with a caption? That is usually not the correct way to do things, you should create a custom container window with a caption and the Scintilla window should be a child window. This child window can take up the entire client area if required.
Using a control directly as a top-level window is not just problematic because of the caption text issue, there are also often notification messages from a control that you need to handle and these are sent to the controls parent window.

Hide/Show the application icon of the Windows taskbar (LabVIEW - WINAPI)

I have an application created with LabVIEW and I need to show/hide the application icon on the Windows taskbar at run time.
I think that WINAPI can be used for this purpose and I tried to use the ShowWindow function (user32.dll)
ShowWindow(hWnd,SW_HIDE) -> hides the application window. The taskbar icon disappears for a second than re-appears.
ShowWindow(hWnd,SW_SHOWMINIMIZED) -> It simply minimizes the application window, so the taskbar icon remains
By default a "normal" visible un-owned window gets a taskbar button and the taskbar button is visible in every state except SW_HIDE.
MSDN also documents a couple of tricks you can use to override the button:
The Shell creates a button on the taskbar whenever an application creates a window that isn't owned. To ensure that the window button is placed on the taskbar, create an unowned window with the WS_EX_APPWINDOW extended style. To prevent the window button from being placed on the taskbar, create the unowned window with the WS_EX_TOOLWINDOW extended style. As an alternative, you can create a hidden window and make this hidden window the owner of your visible window.
... If you want to dynamically change a window's style to one that does not support visible taskbar buttons, you must hide the window first (by calling ShowWindow with SW_HIDE), change the window style, and then show the window.
Another alternative is to use the ITaskbarList interface, it gives you full control over your taskbar button.

Programmatically obtaining a Windows application's tray menu items

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.

Windows. Change drop-down menu position

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.

Borderless Taskbar items: Using a right click menu (VB6)

Even when BorderStyle is set to 0, it is possible to force a window to show up on the taskbar either by turning on the ShowInTaskbar property or by using the windows api directly: SetWindowLong Me.hwnd, GWL_EXSTYLE, GetWindowLong(Me.hwnd, Win.GWL_EXSTYLE) Or Win.WS_EX_APPWINDOW. However, such taskbar entries lack a right-click menu in their taskbar entry. Right-clicking them does nothing instead of bringing up a context menu. Is there a way, to attach a standard or custom handler to it?
Without a hack, I think you're going to be stuck here, I'm sorry to say. When you set the VB6 borderless properties, you inherently disable the control menu. The control menu (typically activated by right-clicking the title bar of a window or left-clicking the icon in the upper left) is what's displayed when you right-click a window in the task bar.
Now, if you're in the mood to hack, you might be able to "simulate" the behavior in such a way that the user doesn't know the difference. I got the idea from this message thread on usenet.
Basically, it sounds like you may be able to hack it by using two forms. One form is minimized right away, and becomes your "stub" in the task bar. The other form is the one you're currently designing (which we'll call the "main" form). The stub form is what actually loads and displays your main form.
The stub form isn't borderless, and must not deactivate the control menu. It is positioned off screen and at the smallest possible size. You'll respond to its form-level events, and then use those to communicate the appropriate behaviors to the borderless form.
That's the general gist of the hack. If I wasn't at work right now, I'd whip up a simple VB6 project and see if I could get it to work for you.

Resources