Identify UWP application as soon as it is launched - winapi

I am monitoring the current foreground process using SetWinEventHook() and EVENT_SYSTEM_FOREGROUND, which gives me the HWND of the window that is currently in the foreground.
I've noticed that UWP Apps are just ApplicationFrameHost.exe processes and the foreground HWND points to an ApplicationFrameHost window. Per another StackOverflow post, to find the actual HWND of the app window, I am supposed to find the first child window of that window that does not belong to the same process, then do my processing there. My processing is just finding the AUMID.
Is there any way to get the app window HWND, or the AUMID, as soon as the ApplicationFrameHost is launched, instead of waiting for the app window to be fully initialized?

Related

Windows How to open apps on specific monitor at startup

I am struggling to find a way to automatically run apps specified monitors at startup.
In my case, I have two apps. One app needs to be opened and maximized on the primary screen and the second app needs to be opened on the secondary screen and maximized.
If you p/invoke ShellExecuteEx you can set the SEE_MASK_HMONITOR flag and the hMonitor member. Starting with Windows 8, Explorer sets STARTUPINFO::hStdOutput to a monitor handle when starting applications from the taskbar.
Whether or not the application you are starting cares is another question. Anything that remembers its previous position is unlikely to care. If the app creates its first window with CW_USEDEFAULT it might work.
Getting something to start maximized is easier. ProcessStartInfo::WindowStyle, SHELLEXECUTEINFO and STARTUPINFO all allow you to force this. The first call to ShowWindow will respect the forced show mode...

Why does WM_CLOSE/DESTROY only partially close my Notepad window?

My scenario is that a program calls my DLL and I use Process.Start(notepad) to start a Notepad window on Windows 10 x64. I don't save the process ID of the started process. Then sometime later, a program calls my DLL again, and I find the Notepad window handle (by matching title strings).
The problem is that when I use the handle to send the window a WM_CLOSE or DESTROY message, the job isn't completed. The window does disappear from my screen. It does disappear from the taskbar. But when I look at windows with Alt-TAB, there it is. It's not really gone; it's just hidden from the taskbar. I'm using this Win32 API call to try to close the window.
[DllImport ("user32.dll", SetLastError = true)]
public static extern bool CloseWindow (IntPtr hWnd);
(1) What am I doing wrong?
(2) Are my expectations out of line? Is it even possible for me (as a DLL running under one process) to order Notepad in another process to close?
I suppose, having the Notepad handle in hand, that I could bring it to the foreground and send Alt+F4 to its keyboard buffer somehow to fake it into thinking that I was typing characters to it. But, that seems like the long way around.
(3) How can I programmatically tell apps to close their windows without bringing them to the foreground and sending them keystrokes, or without sending them mouse clicks on the X close button?
I've looked at other posts on the forum, but they mostly talk about terminating the process with the process APIs - a brute force kill method that isn't really what I want to do. (Besides, I want to close the single window that I'm interested in, not a whole process that might be running a dozen different windows like MS Word...)
I'm using [CloseWindow] to try to close the window.
CloseWindow doesn't close a window -- it minimizes it.
Instead, send the window a WM_CLOSE message:
SendMessage(h, WM_CLOSE, 0, 0);
Try doing this:
SendMessage (hWnd, WM_SYSCOMMAND, SC_CLOSE, 0); // or PostMessage perhaps better
This is what Windows sends when you click on the Close box and is much more likely to work in a wider range of apps since the app will then believe that it has been closed by the user and should act accordingly.

How to automatically restore focus to a launched application on Windows

I have developed a full-screen application that hooks into and launched by a 3rd party/client application. The problem is that the client application gets focus soon after it launches my application, with the result that although my application is full screen, and set to be on top, it does not receive keyboard input, as such the user has to click on it to bring it to focus, which makes for a poor user experience.
How can I restore focus to my application after the client acquires it?
If it matters, my application is written in C++ and has a QT UI.
Not quite the answer but the reason why my application does not have input focus. I'll let Charles Petzold explain (from Programming Windows 5ed, pg 213)
The Window that receives a particular keyboard event is the window that has input focus. The concept of input focus is closely related to the concept of the active window. The window with the input focus is either the active window or a descendant window of the active window -- that is , a child of the active window, or a child of a child of the active window, and so forth.
My Qt application is not spawned spawned by an active window and therefore does not have input focus. The solution therefore would be to parent my application to the active window. Unfortunately this is not straightforward in Qt, if at all possible.
Here is the Qt documentation:
http://doc.qt.io/qt-4.8/qwidget.html#activateWindow
http://doc.qt.io/qt-4.8/qwidget.html#raise
http://doc.qt.io/qt-4.8/qwidget.html#setFocus
Hope it helps when called after launch...

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().

How to overcome full-screen app if I want to show my app

There are cases when one needs to start a process based on some events not involving activity of the mouse of keyboard (from hardware or time-based). It works with ShellExecute and ShellExecuteEx generally, but if there's a full-screen app (the one, created borderless with exactly the dimensions of the screen), this launched application don't become active or even visible. Is there a technique to bring such application to top over this full-screen app? I'm aware about ShellExecuteEx and hProcess manipulation, but it seems it involves very recent api (GetProcessId) and seems that this function has some limitations related to user rights.
Thanks
You can use
SystemParametersInfo (SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (PVOID)0,
SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
to do so before the process start, but you should do this temporary like described in How to ensure process window launched by Process.Start(ProcessStartInfo) has focus of all Forms?.
Please do this only you really need to start a process on top.

Resources