C# 判断窗体是否被遮挡,是否完全显示

思路:

1.获取显示在需判断窗体之上的其他窗体(一个或多个)

2.获取这些窗体的矩形信息

3.判断这些窗体和需判断窗体的矩形是否相交

4.处理一些特殊情况,如任务栏和开始按钮(可略过)

 

适用场景:在窗体失去焦点的情况下,判断窗体是否显示完全

 

具体代码如下:

namespace WindowTimeDev
{
    using System;
    using System.Windows.Forms;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Collections.Generic;

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

        public Rectangle ToRectangle()
        {
            return new Rectangle(Left, Top, Right - Left, Bottom - Top);
        }
    }

    public static class FormHelper
    {
        private static List<Rectangle> ScreenRectangles = new List<Rectangle>();

        static FormHelper()
        {
            foreach (var screen in Screen.AllScreens)
            {
                ScreenRectangles.Add(screen.WorkingArea);
            }
        }

        /// <summary>
        /// 判断窗体是否被遮挡
        /// </summary>
        /// <param name="form">被判断的窗体</param>
        /// <returns>true 被遮挡;false 没被遮挡</returns>
        public static bool IsOverlapped(Form form)
        {
            return isoverlapped(form.Handle, form);
        }

        [DllImport("user32.dll")]
        private static extern IntPtr GetWindow(IntPtr hWnd, uint wWcmd);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);


        private static bool isoverlapped(IntPtr win, Form form)
        {
            IntPtr preWin = GetWindow(win, 3); //获取显示在Form之上的窗口

            if (preWin == null || preWin == IntPtr.Zero)
                return false;

            if (!IsWindowVisible(preWin))
                return isoverlapped(preWin, form);

            RECT rect = new RECT();
            if (GetWindowRect(preWin, ref rect)) //获取窗体矩形
            {
                Rectangle winrect = rect.ToRectangle();

                var sceenRect = ScreenRectangles.Find(x => x.Width == winrect.Width);
                if (sceenRect != null)
                {
                    if (winrect.Y + winrect.Height == sceenRect.Height || winrect.Y == sceenRect.Height) //任务栏。不判断遮挡
                    {
                        Debug.WriteLine("任务栏,不判断遮挡");
                        return isoverlapped(preWin, form);
                    }
                }

                if (winrect.X == 0 && winrect.Y == 0 && winrect.Width == 1 && winrect.Height == 1) //特殊窗体,不判断遮挡
                {
                    Debug.WriteLine("特殊窗体");
                    return isoverlapped(preWin, form);
                }

                Rectangle formRect = new Rectangle(form.Location, form.Size); //Form窗体矩形

                if (formRect.IntersectsWith(winrect)) //判断是否遮挡
                {
                    Debug.WriteLine($"被该窗体遮挡 {winrect}");
                    return true;
                }
            }

            return isoverlapped(preWin, form);
        }

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

 

 

在窗体中使用时的代码如下:

if(FormHelper.IsOverlapped(this))
{
   //具体操作,比如把窗口显示到前台
}

 

posted @ 2015-09-24 09:55  逍遥子k  阅读(3307)  评论(1编辑  收藏  举报