tags:

views:

192

answers:

1

I have a wpf application, for which I need to find out if any other window is over the current window. I can not use IsActive, as that you could have 2 windows side by side (for example IE and the wpf application) and have the other application be active, but not over top of the wpf application.

Essentially I want to know if anything is phsycially over and obscuring part of the wpf window reguardless of activation.

I have tried the following GetWindowRect GetTopWindow

and comparing the topwindow process with the current process, this works but only seems to work once.

any ideas?

A: 

I've done something similar before and I did not find any managed way of doing this. Hence, it's not really a WPF question, but rather "back to unmanaged" or "good old PInvoke" sort of thing. Here's an extract adapted for your task:

XAML definition.

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
    <Label Name="IsSomethingOverLabel">Label</Label>
</Grid>
</Window>

CS code behind.

using System;
using System.Windows;
using System.Windows.Interop;
using System.Runtime.InteropServices;
using System.Windows.Threading;

namespace WpfApplication1 {
using LONG = System.Int32;
using UINT = System.UInt32;    

public partial class Window1: Window {
    DispatcherTimer tmr;

    public Window1() {
        InitializeComponent();

        tmr = new DispatcherTimer();
        tmr.Tick += new EventHandler(tmr_Tick);
        tmr.Start();
    }

    void tmr_Tick(object sender, EventArgs e) {
        RECT Rect2 = GetWindowRect(Handle);
        IntPtr h = GetWindow(Handle, GW_HWNDPREV);
        while(h != IntPtr.Zero) {
            if(IsWindowShown(h))//This is to check that the window found is not minimized etc.
            {
                RECT Rect1 = GetWindowRect(h);
                if(Rect1OverlapsRect2(Rect1, Rect2)) {
                    IsSomethingOverLabel.Content = GetWindowText(h);
                    return;
                }
            }
            h = GetWindow(h, GW_HWNDPREV);
        }
        IsSomethingOverLabel.Content = "Nothing over";
    }

    bool Rect1OverlapsRect2(RECT Rect1, RECT Rect2) {
        return Rect1.left < Rect2.right && Rect1.right > Rect2.left &&
            Rect1.top < Rect2.bottom && Rect1.bottom > Rect2.top;
    }

    private IntPtr Handle {
        get { return new WindowInteropHelper(this).Handle; }
    }


    public const uint GW_HWNDFIRST = 0,
        GW_HWNDLAST = 1,
        GW_HWNDNEXT = 2,
        GW_HWNDPREV = 3,
        GW_OWNER = 4,
        GW_CHILD = 5,
        GW_MAX = 5;
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr GetWindow(IntPtr hWnd, uint wCmd);

    [StructLayout(LayoutKind.Sequential)]
    public struct RECT {
        public LONG left;
        public LONG top;
        public LONG right;
        public LONG bottom;
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
    public static RECT GetWindowRect(IntPtr hWnd) {
        RECT lpRect = new RECT();
        if(!GetWindowRect(hWnd, ref lpRect)) {
            lpRect.top = lpRect.left = lpRect.bottom = lpRect.right = -1;
        }
        return lpRect;
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int GetWindowTextLength(IntPtr hWnd);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int GetWindowText(IntPtr hWnd, string lpString, int nMaxCount);
    public static string GetWindowText(IntPtr hWnd) {
        int len = GetWindowTextLength(hWnd) + 1;
        string s = new string(' ', len);
        if(GetWindowText(hWnd, s, len) != 0) {
            return s.Substring(0, len - 1);
        } else {
            return "";
        }
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern bool IsWindowVisible(IntPtr hWnd);
    public const int SW_HIDE = 0,
        SW_SHOWNORMAL = 1,
        SW_NORMAL = 1,
        SW_SHOWMINIMIZED = 2,
        SW_SHOWMAXIMIZED = 3,
        SW_MAXIMIZE = 3,
        SW_SHOWNOACTIVATE = 4,
        SW_SHOW = 5,
        SW_MINIMIZE = 6,
        SW_SHOWMINNOACTIVE = 7,
        SW_SHOWNA = 8,
        SW_RESTORE = 9,
        SW_SHOWDEFAULT = 10,
        SW_MAX = 10;
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT {
        public LONG x;
        public LONG y;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct WINDOWPLACEMENT {
        public UINT length;
        public UINT flags;
        public UINT showCmd;
        public POINT ptMinPosition;
        public POINT ptMaxPosition;
        public RECT rcNormalPosition;
    }

    public static bool IsWindowShown(IntPtr hWnd) {
        bool res = IsWindowVisible(hWnd);
        WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
        if(res && GetWindowPlacement(hWnd, ref placement)) {
            switch(placement.showCmd) {
                case SW_RESTORE:
                case SW_SHOW:
                case SW_SHOWMAXIMIZED:
                case SW_SHOWNA:
                case SW_SHOWNORMAL:
                    res = true;
                    break;
                default:
                    res = false;
                    break;
            }
        }
        return res;
    }
}
}

Having a fresh look at the code, GetWindowPlacement could probably be sufficient by itself, eliminating the GetWindowRect call, you can also try that.

Stanislav Kniazev