Fka
Fka

Reputation: 6234

How to check whether application is running fullscreen mode on any screen?

I'd like to check, if any screen hosts application in fullscreen mode. I have solution only for one screen which is code copied from here: [WPF] [C#] How-to : Detect if another application is running in full screen mode. This solution is based on

[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

which gathers only active window handle. The problem is, I have two screens. I've searched many sites but none of them answers my question. It is not about capturing screenshot, which is simple and doesn't rely on P/Invoke.

Is this possible?

Upvotes: 2

Views: 3567

Answers (3)

Fka
Fka

Reputation: 6234

I wrote piece of code which is working:

namespace EnumWnd
{
using System;
using System.Runtime.InteropServices;
using System.Text;

[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
    public int Left;

    public int Top;

    public int Right;

    public int Bottom;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal struct MonitorInfoEx
{
    public int cbSize;
    public Rect rcMonitor;
    public Rect rcWork;
    public UInt32 dwFlags;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string szDeviceName;
}

internal class Program
{
    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    protected static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    protected static extern int GetWindowTextLength(IntPtr hWnd);

    [DllImport("user32.dll")]
    protected static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);

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

    [DllImport("User32")]
    public static extern IntPtr MonitorFromWindow(IntPtr hWnd, int dwFlags);

    [DllImport("user32", EntryPoint = "GetMonitorInfo", CharSet = CharSet.Auto,
        SetLastError = true)]
    internal static extern bool GetMonitorInfoEx(IntPtr hMonitor, ref MonitorInfoEx lpmi);

    protected static bool EnumTheWindows(IntPtr hWnd, IntPtr lParam)
    {
        const int MONITOR_DEFAULTTOPRIMARY = 1;
        var mi = new MonitorInfoEx();
        mi.cbSize = Marshal.SizeOf(mi);
        GetMonitorInfoEx(MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY), ref mi);

        Rect appBounds;
        GetWindowRect(hWnd, out appBounds);
        int size = GetWindowTextLength(hWnd);
        if (size++ > 0 && IsWindowVisible(hWnd))
        {
            var sb = new StringBuilder(size);
            GetWindowText(hWnd, sb, size);

            if (sb.Length > 20)
            {
                sb.Remove(20, sb.Length - 20);
            }

            int windowHeight = appBounds.Right - appBounds.Left;
            int windowWidth = appBounds.Bottom - appBounds.Top;

            int monitorHeight = mi.rcMonitor.Right - mi.rcMonitor.Left;
            int monitorWidth = mi.rcMonitor.Bottom - mi.rcMonitor.Top;

            bool fullScreen = (windowHeight == monitorHeight) && (windowWidth == monitorWidth);

            sb.AppendFormat(" Wnd:({0} | {1}) Mtr:({2} | {3} | Name: {4}) - {5}", windowWidth, windowHeight, monitorWidth, monitorHeight, mi.szDeviceName, fullScreen);

            Console.WriteLine(sb.ToString());
        }
        return true;
    }

    private static void Main()
    {
        while (true)
        {
            EnumWindows(EnumTheWindows, IntPtr.Zero);
            Console.ReadKey();
            Console.Clear();
        }
    }

    protected delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
}

}

Thanks for @SamAxe and @quetzalcoatl for providing me useful tips.

Upvotes: 1

KeyNone
KeyNone

Reputation: 9190

You could use EnumWindows in conjunction with Screen.FromHandle. And maybe GetWindowRect() for calculations.

Something like (pseudo-code!):

//------------------------------
//this sample code is taken from http://pinvoke.net/default.aspx/user32/EnumWindows.html

public delegate bool EnumedWindow(IntPtr handleWindow, ArrayList handles);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumWindows(EnumedWindow lpEnumFunc, ArrayList lParam);

public static ArrayList GetWindows()
{    
    ArrayList windowHandles = new ArrayList();
    EnumedWindow callBackPtr = GetWindowHandle;
    EnumWindows(callBackPtr, windowHandles);
    return windowHandles;     
}

private static bool GetWindowHandle(IntPtr windowHandle, ArrayList windowHandles)
{
    windowHandles.Add(windowHandle);
    return true;
}

//------------------------------

[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, [In,Out] ref Rect rect);

[StructLayout(LayoutKind.Sequential)]
private struct Rect
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}

static void Main() {
    foreach(IntPtr handle in GetWindows())
    {
      Screen scr = Screen.FromHandle(handle);

      if(IsFullscreen(handle, scr))
      {
          // the window is fullscreen...
      }
    }
}

private bool IsFullscreen(IntPtr wndHandle, Screen screen)
{
    Rect r = new Rect();
    GetWindowRect(wndHandle, ref r);
    return new Rectangle(r.Left, r.Top, r.Right-r.Left, r.Bottom-r.Top)
                          .Contains(screen.Bounds);
}

Upvotes: 1

quetzalcoatl
quetzalcoatl

Reputation: 33566

No ready-to-use solution here, but let's see..

Get list of all displayed windows and check positions and sizes of those windows - possible, lots of tools does it, many articles on that, I'll skip this one. Then, you can call MonitorFromWindow for each or some windows and compare window dimensions&position against monitor info. If windowpos ~= 0,0 and windowsize ~= monitorresolution you could assume that this window is in fullscreen mode.

On the other hand, if already having a list of all HWNDs, then why not just Query the window for its placement and check the WINDOWPLACEMENT.showCmd for SW_MAXIMIZE/SW_SHOWMAXIMIZED flags. That won't tell you which monitor is it, but should tell you at least if the window is maximized and if it's enough for you..

I don't know how fast/slow would it be to do it like that, but, yes, it seems possible.

Upvotes: 1

Related Questions