Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if window is really visible in Windows Forms?

Normally you use Form.Visible to check if Window is visible at all. But sometimes on the screen window is below other windows so it's really invisible.

So how to check in c# Windows Forms if window is really visible or not?

I would like to accomplish this: when I click CTRL+K on my keyboard and my window is visible on my screen it does nothing. But when it's underneath other windows it pops to the top (Bring to front).

kind regards

like image 835
Tom Smykowski Avatar asked Oct 30 '09 13:10

Tom Smykowski


People also ask

How do you check if a Windows Form is open or not?

Just call Show method on the instance. You can check Form. Visible property to check if the form open at the moment.

How do I turn off WinForms full screen?

In WinForms, you do that by setting the FormBorderStyle property to one of the following: FormBorderStyle. FixedSingle , FormBorderStyle. Fixed3D , or FormBorderStyle.

Are Windows Forms front end?

Back-end refers to stuff going on behind the scenes, i.e. not directly visible by the user, and front-end refers to the opposite - the stuff that's directly visible. Hence, WinForms is clearly a front-end thing.


1 Answers

I googled trough the web, but coudn't find any straight answer to see if a part of a window is truly visible to the user. I actually needed a way to "hittest" the form, if the mouse is currently on top of the visible part of the window. I thought I'd share the code which took several days to accomplish:

public class VisibilityTester
{
    private delegate bool CallBackPtr(int hwnd, int lParam);
    private static CallBackPtr callBackPtr;

    /// <summary>
    /// The enumerated pointers of actually visible windows
    /// </summary>
    public static List<IntPtr> enumedwindowPtrs = new List<IntPtr>();
    /// <summary>
    /// The enumerated rectangles of actually visible windows
    /// </summary>
    public static List<Rectangle> enumedwindowRects = new List<Rectangle>();

    /// <summary>
    /// Does a hit test for specified control (is point of control visible to user)
    /// </summary>
    /// <param name="ctrlRect">the rectangle (usually Bounds) of the control</param>
    /// <param name="ctrlHandle">the handle for the control</param>
    /// <param name="p">the point to test (usually MousePosition)</param>
    /// <param name="ExcludeWindow">a control or window to exclude from hit test (means point is visible through this window)</param>
    /// <returns>boolean value indicating if p is visible for ctrlRect</returns>
    public static bool HitTest(Rectangle ctrlRect, IntPtr ctrlHandle, Point p, IntPtr ExcludeWindow)
    {
        // clear results
        enumedwindowPtrs.Clear();
        enumedwindowRects.Clear();

        // Create callback and start enumeration
        callBackPtr = new CallBackPtr(EnumCallBack);
        EnumDesktopWindows(IntPtr.Zero, callBackPtr, 0);

        // Go from last to first window, and substract them from the ctrlRect area
        Region r = new Region(ctrlRect);

        bool StartClipping = false;
        for (int i = enumedwindowRects.Count - 1; i >= 0; i--)
        {
            if (StartClipping && enumedwindowPtrs[i] != ExcludeWindow)
            {
                r.Exclude(enumedwindowRects[i]);
            }

            if (enumedwindowPtrs[i] == ctrlHandle) StartClipping = true;
        }

        // return boolean indicating if point is visible to clipped (truly visible) window
        return r.IsVisible(p);
    }

    /// <summary>
    /// Window enumeration callback
    /// </summary>
    private static bool EnumCallBack(int hwnd, int lParam)
    {
        // If window is visible and not minimized (isiconic)
        if (IsWindow((IntPtr)hwnd) && IsWindowVisible((IntPtr)hwnd) && !IsIconic((IntPtr)hwnd))
        { 
            // add the handle and windowrect to "found windows" collection
            enumedwindowPtrs.Add((IntPtr)hwnd);

            RECT rct;

            if (GetWindowRect((IntPtr)hwnd, out rct))
            {
                // add rect to list
                enumedwindowRects.Add(new Rectangle(rct.Left, rct.Top, rct.Right - rct.Left, rct.Bottom - rct.Top));
            }
            else
            {
                // invalid, make empty rectangle
                enumedwindowRects.Add(new Rectangle(0, 0, 0, 0));
            }
        }

        return true;
    }


    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool IsWindowVisible(IntPtr hWnd);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool IsWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool IsIconic(IntPtr hWnd);

    [DllImport("user32.dll")]
    private static extern int EnumDesktopWindows(IntPtr hDesktop, CallBackPtr callPtr, int lPar);

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

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
        public int Left;        // x position of upper-left corner
        public int Top;         // y position of upper-left corner
        public int Right;       // x position of lower-right corner
        public int Bottom;      // y position of lower-right corner

        public override string ToString()
        {
            return Left + "," + Top + "," + Right + "," + Bottom;
        }
    }
}
like image 173
Jaska Avatar answered Sep 28 '22 16:09

Jaska