C#/WINAPI: SetWindowPos() - c#

I am using SetWindowPos() to try and send Windows to back/front of the z-order.
It seems to work for the most part however I am noticing for certain windows it just won't work although the function will return success.
For example Window Task Manager seems to work perfectly fine but the other windows aren't responding properly to the function call.
Any insights into what may be happening? I know the information is sparse however I am not sure what to include.

Pretty much seems to work using SetForegroundWindow.
From what I could discern it seems that using SetWindowPos and setting a window to HWND_TOP will make it top of the z-order following the foreground window.
Meaning that once the foreground window is removed (minimized/closed) it will then be the next one at the TOP.

I too have hod problems with this across processes. This from the MS documentation:
To use SetWindowPos to bring a window to the top, the process that owns the window must have SetForegroundWindow permission.
might be the cause?

Related

Extend another application's title bar

I'm working on an open-source .NET clone (GitHub) of DeskPins by Elias Fotinis (direct download off Google Drive). Its main function is to make other windows always-on-top. When they are on top, a pin icon is added to the title bar, which looks like this:
The pin icon moves with the window during drag and drop, and really looks like a part of it. It even responds to click event, which cancels always on top status and removes the icon from display.
Question. Is it possible to implement something like this in C# (and p/invoke, I'd assume)?
Research
I tried to run this project.
Add Your Control On Top Another Application # CodeProject
It's a WPF demo, which is supposed to add a custom control to the title bar. Does not seem to work on Windows 7 x64. Not sure if it's the OS or otherwise. Problem - z-order is not consistent, title bar appears on top of other windows as well, and it does not move with the window, it tries, but lots of visual artifacts and flicker.
Tried to apply this solution to #1:
Attach form window to another window in C#
Basically replacing relevant call to SetWindowLong with this pattern:
SetWindowLong(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD);
SetParent(guestHandle, hostHandle);
This change broke everything, so nothing was added to the title bar. Could be that it's not meant for title bars, only for the user area of the form.
In any case, if there is a simple solution, please share your wisdom. If not, I would appreciate any hints and/or links for me to investigate the topic further.
Here's how I've done this in DeskPins.
Each pin is a popup window with a custom HRGN defining its shape. I did experiment with injecting a DLL into processes using hooks and drawing on the caption, but that was too messy for me back then.
DeskPins creates the pin using WS_POPUP, WS_EX_TOPMOST and WS_EX_TOOLWINDOW, with 0 as the parent window. Then it immediately sends it a message (WM_PIN_ASSIGNWND), passing the target window to be pinned and the polling rate in msec. After that, the pin runs independently from DeskPins and they only send information messages to each other.
The pin handles WM_PIN_ASSIGNWND by setting the target window as its parent, making it top-most and starting a polling timer. To set the parent it uses:
SetWindowLong(hPin, GWL_HWNDPARENT, (LONG)hPinned);
Note that Microsoft warns against setting the parent like this and instead suggests using SetParent(). However, SetParent() does some internal processing which prevents it from working across processes. Using SetWindowLong(GWL_HWNDPARENT) essentially tricks the window manager to accept this. It's a bit of a hack, but, hey... it works.
The polling timer runs continuously and tests whether the target window is destroyed, hidden, moved or had its WS_EX_TOPMOST flag changed and responds appropriately.

Restore Windows to Size They Were Previous to Being Minimized

I'm trying to use WinAPI to bring any open window to the foreground. I've tried many different ways of accomplishing this but none that worked out perfectly. Methods I've tried include SwitchToThisWindow, BringWindowToTop, SetActiveWindow, and SetForegroundWindow using the AttachInputThread and they all tended to fail if the target window was minimized. More recently I've tried OpenIcon and ShowWindow (with the RESTORE command) to unminimize windows, but that too has presented a problem, in that, both of those methods unminimize the window to it's "Normal" or "Original" state regardless of whether it was "Normal" or "Maximized" before it was minimized.
The current solution I can think of is to intercept the minimize message to any open window and store its state before it's minimized and restore it using that stored state. However, this would require me hooking into every process I'd want to restore which I'd really rather not do.
So my question is, how do unminimize a window to the state it was in before it was minimized?
Your solution is correct. You have to store the window size so you can "reconstitute it" to the same size. You should also store position, as well as size, if you want it to look correct. Much of this is abstracted if you don't dig into the bowels like this.

Issue with EnumWindows

When enumerating windows using EnumWindows, I get hundreds of handles instead of one per open window on my desktop.
First of all, i am curious if this is the correct behavior.
Secondly, trying to get a difference between open windows before and after launching a process returns 15-20 new handles. I am wondering if there is a way to filter these based on some flag, i really need just the mainwindow handle.
Any ideas?
To get the main window of a process, use the Process.MainWindowHandle property.
To answer your question, you can see exactly what all of the handles are using Spy++.
In short, many applications will create hidden windows to run message loops.
You can filter within the enum callback by checking IsWindowVisible() & ignoring invisible system/message sink windows.

How can we prevent popup windows appearing on top of the application?

I have a fullscreen window, and I want to prevent pop up windows that appear at the right bottom corner of my screen. I set the Topmost property to true, but apparently it does not help. I also tried activating the form and giving it the focus once it got deactivated, but that did not help either. What is a way to ignore such windows while the user is engaged with the fullscreen app? I am .NET programming in C#.
You can't do it, this fails the "what if two programs tried to do this" test:
those popups are just normal windows like yours, they also use the same top-most style you are using.
if there was a way to always be above other topmost windows they would have used it too rendering it useless (because the authors of the other apps are just as concerned about the user missing their "super important" notifications as you are about them interfering with your full screen app).
You can try and play dirty tricks to force your window to the top of the top-most z-order, but those popups are likely to use the exact same tricks, again making this all useless (and as an extra bonus all those dirty tricks can turn your app into a compatibility nightmare).
You can disable these balloon notifications using these steps:
Click Start, Run and type regedit
Navigate to the following subkey:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced
In the right pane, create a DWORD value named EnableBalloonTips
Double-click the new entry, and give it a value of 0.
Quit Registry Editor.
Log off Windows (this is not very cool...), and then log back on for the changes to take effect.
if you need help in how doing this by program, don't hesitate to ask ;)
I don't think that you can block all the popups, windows might not let you do that. But you can try with SetWindowPos function and pass it HWND_TOP parameter. It might work a little better than Topmost = true.
I used a sys tray popup control on my personal project SvnRadar written in WPF.
The control is at the http://www.hardcodet.net/projects/wpf-notifyicon written by Philipp Sumi.
Very nice.Only thing you will be need to "detach" it from the SysTray screen coordinates and
make it appear where you wish.
Hope it helps.
Good luck.

Bringing Window to the Front in C# using Win32 API

I am writing an application that needs to bring window of an external app to the foreground, and not necessarily steal focus (there is a setting the user can toggle to steal/not steal focus).
What is the best way to go about this using the win32 API? I have tried SetForeground() but it always steals focus and does not consistenly work.
What is the best way to go about this? Any thoughts?
SetForegroundWindow is supposed to steal focus and there are certain cases where it will fail.
The SetForegroundWindow function puts the thread that created the specified window into the foreground and activates the window. Keyboard input is directed to the window
Try capturing the focus with SetCapture prior to making the call. Also look into different ways of bringing the window to the front: SetForeGroundWindow, SetActiveWindow, even simulating a mouse click can do this.
What is the difference between SetForeGroundWindow, SetActiveWindow, and BringWindowToTop? It appears as if they all do the same thing.
According to MSDN, SetForeGroundWindow will activate the window and direct keyboard focus to it. This attempts to work even when your process is in the background. SetActiveWindow does the same thing as SetForeGroundWindow, but it doesn't do anything if your application isn't the frontmost application. Finally, BringWindowToTop only brings the window to the top, and doesn't change the keyboard focus.
You can try the BringWindowToTop function to not steal focus. I haven't used it, but it seems to be what you're looking for.
Have you tried using SetWindowPos. This is the canonical function for moving, resizing and setting z-order in Windows. There is a SWP_NOACTIVATE flag you can use. Look at http://msdn.microsoft.com/en-us/library/ms633545(VS.85).aspx. I have not tried this on a window belonging to another process, but it is probably worth a try.
SetWindowPos + SWP_NOACTIVATE does the job.
You could use FindWindow to get the HWND of the window, then use the BringWindowToTop function found in the Win32 API.

Categories