2

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?

Fka
  • 6,044
  • 5
  • 42
  • 60
  • `GetForgroundWindow` just gives you a windows handle (hWnd). Use any method of enumerating windows that you like - they will all give you an hWnd - and plug those values in instead of the foreground hWnd. – Sam Axe Aug 27 '15 at 08:40
  • Try this: http://www.codewrecks.com/blog/index.php/2014/01/29/change-appearance-of-a-control-if-the-windows-is-maximized-in-wpf/ By using the binding you can store the variable to check if the sceen is maximized – PieterSchool Aug 27 '15 at 08:41
  • @PieterSchool - it's not about WPF, but thanks for your time :) – Fka Aug 27 '15 at 08:43
  • @Fka I assumed it because of the link sorry – PieterSchool Aug 27 '15 at 08:43
  • @SamAxe - okay, I found some solution for enumerating windows. Do you know if it's possible to check, on which screen window lays? – Fka Aug 27 '15 at 08:50
  • Get the [window bounds](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633519(v=vs.85).aspx) and `Intersect` or `Contains` it with each [`Screen`](https://msdn.microsoft.com/en-us/library/system.windows.forms.screen(v=vs.110).aspx) bounds. – Sam Axe Aug 27 '15 at 08:54
  • @SamAxe - yes, but let's assume that my Screen1 is 600x800 and Screen2 is 1000x1400. I have windowed-mode Windows of size 600x800 in Screen2. It will be detected as fullscreen-mode because of one of my screens' sizes or as a normal window? – Fka Aug 27 '15 at 09:10
  • 2
    @Fka: Imagine a piece of paper. Draw two rectangles of different sizes, each sharing a border with the other. The paper represents, for lack of a better term, your virtual desktop. The rectangles represent your monitors. `GetWindowRect` and `Screen.Bounds` are given in virtual desktop coordinates. There's no need to fret over monitor resolutions. – Sam Axe Aug 27 '15 at 09:35

3 Answers3

1

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.

quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107
1

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);
}
KeyNone
  • 8,745
  • 4
  • 34
  • 51
1

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.

Fka
  • 6,044
  • 5
  • 42
  • 60