Windows 10 Need to use HWND_TOPMOST for two windows, API

Elsy

New Member
I have a project where i have two windows that i fullscreen on my two monitors. i have successfully been able to make one of these windows always on top by using:

SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);

But when i try to set my second window on top, it deactivates HWND_TOPMOST on my first window. I am aware that this is a feature in windows API, but i really need to go around it somehow.

How can i have two windows utalize HWND_TOPMOST at the same time?
 
The HWND_TOPMOST flag from the SetWindowPos() function is used to bring a window to the top of the Z-order. Windows retains this setting even when you set it for multiple different windows. So when you set HWND_TOPMOST for one window, you're not necessarily deactivating it for the other.

However, the perceived issue could be associated with focus. On a multi-monitor setup when you activate one window, the system will automatically deactivate the other previously active window, although both windows are still 'TopMost'. If you try to interact with an overlapped region (i.e. shared by both windows), the one with the focus will be brought to the front.

If you simply want to have two windows covering the full screen on dual monitors, setting each of them to HWND_TOPMOST should work. Make sure the two windows don't overlap in terms of their area and ensure that you're handling the WM_ACTIVATEAPP message and related messages properly to prevent the application from minimizing or losing focus unintentionally.

Here's a sample code assuming you have hWnd1 and hWnd2 as your two window handles:

```cpp
SetWindowPos(hWnd1, HWND_TOPMOST, monitor1_x, monitor1_y, monitor_width, monitor_height, SWP_SHOWWINDOW);
SetWindowPos(hWnd2, HWND_TOPMOST, monitor2_x, monitor2_y, monitor_width, monitor_height, SWP_SHOWWINDOW);
```

This code makes both windows topmost and position them according to the coordinates of the two monitors. Adjust values of monitor1_x, monitor1_y, monitor2_x, monitor2_y, monitor_width, and monitor_height according to your display setup.

Remember, the behavior can differ based on the specific requirements of your program. Try to handle transitions of the window's z-order position and its activated state properly.
It's also essential to note that topmost windows should be used sparingly, as they can easily interfere with the user's experience if overused or misused.
 
Then it seems i have another problem, because when setting both windows to HWND_TOPMOST only one of them work. any help would be apreciated here is my code:


using System;
using System.Runtime.InteropServices;
using UnityEngine;

public class OverlayWindow : MonoBehaviour
{
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);

[DllImport("user32.dll")]
private static extern bool IsWindowVisible(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder lpString, int nMaxCount);

[DllImport("user32.dll")]
private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);

[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

[DllImport("user32.dll")]
static extern int SetLayeredWindowAttributes(IntPtr hWnd, uint crKey, byte bAlpha, uint dwFlags);

private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

private const int GWL_EXSTYLE = -20;
private const int WS_EX_LAYERED = 0x80000;
private const int LWA_COLORKEY = 0x00000001;
private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
private static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
private static readonly IntPtr HWND_TOP = new IntPtr(0);
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_SHOWWINDOW = 0x0040;

private void Start()
{
EnumWindows(EnumWindowsCallback, IntPtr.Zero);
Application.runInBackground = true; //Makes sure it's always running
}

private bool EnumWindowsCallback(IntPtr hWnd, IntPtr lParam)
{
//if (!IsWindowVisible(hWnd)) return true; // Skip invisible windows

// Get the process ID associated with the window
GetWindowThreadProcessId(hWnd, out int processId);

// Filter windows based on process ID if needed
if (processId == GetCurrentProcessId())
{
// Apply settings to the window
SetWindowStyle(hWnd);
}

return true; // Continue enumeration
}

private void SetWindowStyle(IntPtr hWnd)
{
// Make the window layered and transparent
SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_LAYERED);
SetLayeredWindowAttributes(hWnd, 0, 0, LWA_COLORKEY);

// Make the window topmost
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
}

private int GetCurrentProcessId()
{
return System.Diagnostics.Process.GetCurrentProcess().Id;
}
}
 
Last edited:
Back
Top