C# winform check if control is physicaly visible

后端 未结 9 1616
有刺的猬
有刺的猬 2020-12-09 01:58

Is it possible to determine if at least one pixel of a control can be seen (by a property or maybe using event notification).

NB : I am not looking for the Visible p

相关标签:
9条回答
  • 2020-12-09 02:56

    If a control is visible the Paint event will be called (repeatedly).

    Normally for not visible controls, this event will not be called.

    0 讨论(0)
  • 2020-12-09 02:59

    I somewhat finished the answer by Hans Passant. The function below tests for all four corners of the form.

            /// <summary>
        /// determines if a form is on top and really visible.
        /// a problem you ran into is that form.invalidate returns true, even if another form is on top of it. 
        /// this function avoids that situation
        /// code and discussion:
        /// https://stackoverflow.com/questions/4747935/c-sharp-winform-check-if-control-is-physicaly-visible
        /// </summary>
        /// <param name="child"></param>
        /// <returns></returns>
        public bool ChildReallyVisible(Control child)
        {
            bool result = false;
    
            var pos = this.PointToClient(child.PointToScreen(Point.Empty));
    
            result = this.GetChildAtPoint(pos) == child;
            //this 'if's cause the condition only to be checked if the result is true, otherwise it will stay false to the end
            if(result)
            {
                result = (this.GetChildAtPoint(new Point(pos.X + child.Width - 1, pos.Y)) == child);
            }
            if(result)
            {
                result = (this.GetChildAtPoint(new Point(pos.X, pos.Y + child.Height - 1)) == child);
            }
            if(result)
            {
                result = (this.GetChildAtPoint(new Point(pos.X + child.Width - 1, pos.Y + child.Height - 1)) == child) ;
            }
            return result;
        }
    
    0 讨论(0)
  • 2020-12-09 03:00

    Tried the above but kept getting true even if the winform was covered by another app.

    Ended up using the following (inside my winform class):

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace yourNameSpace
    {
        public class Myform : Form
        {
    
            private void someFuncInvokedByTimerOnMainThread()
            {
                bool isVisible = isControlVisible(this);
                // do something.
            }
    
            [DllImport("user32.dll")]
            static extern IntPtr WindowFromPoint(System.Drawing.Point p);
    
    
            ///<summary><para>------------------------------------------------------------------------------------</para>
            ///
            ///<para>           Returns true if the control is visible on screen, false otherwise.                </para>
            ///
            ///<para>------------------------------------------------------------------------------------</para></summary>
            private bool isControlVisible(Control control)
            {
                bool result = false;
                if (control != null)
                {
                    var pos = control.PointToScreen(System.Drawing.Point.Empty);
                    var handle = WindowFromPoint(new System.Drawing.Point(pos.X + 10, pos.Y + 10)); // +10 to disregard padding   
                    result = (control.Handle == handle); // should be equal if control is visible
                }
                return result;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题