How to get the Window hosting a UIElement instance - window

I'm trying to get the Window instance which is hosting a UIElement instance in WinUI 3.
There's a helper method in the Window class in .NET (see this thread) but i cannot find something similar for C++/WinRT.
I tried VisualTreeHelper as some suggested but it doesn't help here; none of the parents were of type winrt::Microsoft::UI::Xaml::Window.
Is it possible to get the hosting Window of a dependency object?

If it is a UWP application, each UI thread already has a Window that can be retrieved using the static Window.Current property.
If it is a C++/WinRT WinUI3 in Desktop application, Window implements IWindowNative to enable interop through the Window's HWND (WindowHandle). You could get the handle of the Window and do what you want. Like:
// Get the current window's HWND by passing in the Window object
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
For more information, please check: Window Class-Windows App SDK

Related

WinUI3 : How to get the WinUI3 window back from its respective HWND

I'm working on the WinUI3 desktop application. I'm trying to set an ID to the winui3 window and get the WinUI3 window back with only the ID. I could not find any direct way to do this.
I tried to extract HWND from the WinUI3 window and set the ID using SetProp.
uWindow.try_as<::IWindowNative>()->get_WindowHandle(&hWnd);
SetProp(hWnd,"ID","WindowID")
But it doesn't fit well as per my requirements. I want to get the WinUI3 Window back when I have only the ID, I was able to get the HWND of the window back from the ID which I set as the property for HWND, but I was not able to get back the WinUI3 Window from that HWND.
It would be of great help if you could help me get the WinUI3 window back from HWND of its native window.
Thank you
You could try to follow the following steps:
1, Retrieve the HWND for your existing window object via Retrieve a window handle
2, Pass that HWND to the GetWindowIdFromWindow interop function to retrieve a WindowId.
3, Pass that WindowId to the static AppWindow.GetFromWindowId method to retrieve the AppWindow.
For more details I suggest you could refer to the Doc: Manage app windows (Windows App SDK)

What type of Resource is a Popup Menu in 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.

How to intercept a window message in a shell extension

I have a shell extension that needs to reload its configuration when a specific window message (custom message registered with RegisterWindowMessage) is broadcasted by another application.
I tried several approaches to intercept the message:
Installing a window subclass callback on a window of Windows Explorer, using SetWindowSubclass. This works on Window 7, but not on Windows 8, because apparently DllMain is not called on the main thread, and SetWindowSubclass doesn't work from another thread. This is mentioned in the documentation:
You cannot use the subclassing helper functions to subclass a window across threads
Installing a hook for CALLWNDPROC, using SetWindowsHookEx. Because I don't want to slow down the whole system, I install the hook for a specific thread only (the explorer's main thread). This works on Windows 8, but not on Windows 7... I suspect this is because I'm hooking on the wrong thread, but I'm not sure. And anyway, this approach seems overly intrusive.
Creating a message-only window to handle the message. This doesn't work at all, because message-only windows don't receive broadcasted messages.
Is there a reliable way to receive a window message in a shell extension?
A window message initially seemed to be the easiest way to notify the shell extension, but if you think another mechanism would be more appropriate, I'm open to suggestions.
Create a hidden window and listen for the message in its window procedure.
Register a window class that has default values for all the fields apart from the window procedure and class name. You don't need to specify anything else in the window class since the window will never be visible.
When you create the window, pass 0 for the window style. Specifically exclude WS_VISIBLE.
Pass 0 for the WndParent when you create the window. This will make it a top level window and so eligible to receive broadcast messages.

Can you have a win32 program that consists solely of a tray (notification) icon?

I have a program that literally consists of a tray icon. No GUI is needed. However, when writing the win32 code, is it necessary to still initialize a hWnd object to be associated with the tray icon?
For instance, it is normal to have a the NOTIFYICONDATA hWnd field point to the window's handle. Like
nid.hWnd = hwnd;
Essentially, will my icon be able to still receive messages if i set
nid.hwnd = NULL;
How would you receive messages without a window?
Yes you need a window associated with the tray icon.
You could create a message-only window by specifying HWND_MESSAGE creating the window. However, message-only windows do not receive broadcast messages and you would miss out on the TaskbarCreated message. This message tells your application that explorer.exe has restarted and that your application needs to re-add its notification icons. Rather important. So create a window that never becomes visible: never call ShowWindow().

Need to bring application to foreground on Windows

I've got two applications I'm developing using Qt on windows. I want the user to be able to press a button in one application which makes the other application come to the foreground. (The programs communicate using QLocalSocket and named pipes.)
Currently I'm using Qt's QWidget::activateWindow() which occasionally brings the application to the foreground, but most of the time it just highlights the program on the taskbar.
Can someone please tell me how to do this, preferably using Qt although failing that using the WIN32 API would be fine.
Unfortunately, I couldn't find a way to do this only with Qt. I solved it using Chris Becke's suggestion of calling SetForegroundWindow from the currently active application.
Are you sure this is not a debugging issue? The deal is, if an application HAS the foreground, it is allowed to change the foreground.
Clicking a button on window A will give that windows thread foreground activation. If it calls SetForegroundWindow (or equivalent) on the other window, that window WILL be given the foreground.
If, on the other hand, it simply sends a message to the other app, which tries to SetForeground on itself, that will fail. AllowSetForegroundWindow is used in situations where a 'legacy' app needs to be given permission - by a foreground app - to take the foreground. Once again, AllowSet... only works if called from a thread that owns the current active foreground window.
On top of the QWidget::activateWindow method, you should call QWidget::raise !
This is what is said here.
I have a similar case.
I have two Qt applications, A and B, which communicate on a socket.
I would like to bring a window of application B up, through a button on application A.
I found that sometimes the widget state is not set correctly, so in the event() function of my applicatons B's widget I did the following:
bool MyWidgetB:event ( QEvent * e )
{
QEvent::Type type = e->type ();
// Somehow the correct state of window is not getting set,
// so doing it manually
if( e->type() == QEvent::Hide)
{
this->setWindowState(WindowMinimized);
}
else if( e->type() == QEvent::Show )
{
this->setWindowState((this->windowState() & ~WindowMinimized) |
WindowActive);
}
return QWidget::event(e);
}
I'm sending a command from application A to B. On receiving it, application B calls the following function on itself:
void BringUpWidget(QWidget* pWidget)
{
pWidget ->showMinimized(); // This is to bring up the window if not minimized
// but beneath some other window
pWidget ->setWindowState(Qt::WindowActive);
pWidget ->showNormal();
}
This works for me, on Windows XP, with Qt 3.3. My MainWidget is is derived from a QWidget.
I have found this is also working with a widget derived from QMainWindow, but with some issues. Like if some other child windows are open.
For such a case I store the position of the child windows and hide them, then use the BringUpWidget function to bring my MainWindow widget, and then restore the child windows.
This is kind of cheesy, but it works for me:
this->setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
this->show();
this->setWindowFlags(Qt::FramelessWindowHint);
this->show();
Or, if you don't have other flags,
this->setWindowFlags(Qt::WindowStaysOnTopHint);
this->show();
this->setWindowFlags(0);
this->show();
WindowStaysOnTopHint will almost always force the window to the foreground. Afterwards, you don't really want the window to always stay on top, so reset to whatever the previous flags were.
I think the APIs you need are AllowSetForegroundWindow() and SetForegroundWindow(). I don't know what the equivalent Qt calls are.
Use showNormal() to go from an iconified state to a visible state.

Resources