Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Как определить отображается ли control


Автор: elsan 20.7.2011, 12:09
Добрый день.

Есть TabControl на вкладках, которого расположены TextBox. При переключении вкладок нужно выставить флаг, что некоторые  TextBox не отображаются и информацию в них обновлять не нужно. Вариант ловить событие изменения вкладок не желателен.
Какое событие или фукнция возвращает состояние контрола, выведен он на экран или нет?

VisibleChanged срабатывает только при Visible=true. Может кто-то сталкивался с подобным.
Спасибо.

Автор: AlexNagits 20.7.2011, 18:01
Привет, elsan!

Цитата(elsan @  20.7.2011,  12:09 Найти цитируемый пост)
Есть TabControl на вкладках, которого расположены TextBox

Из-за запятой я только с 5 раза понял смысл предложения  smile 

А вопрос очень даже хороший. Я бы его запостил в разделе "не для новичков". 
Ясно, что про Visible надо вообще забыть. Можно скрыть элемент с экрана многими способами и Visible останется true.

За часок-другой набросал решение в виде класса ReallyVisibility, проверил для разных случаев скрытия элемента с экрана:
    Скрытие элемента прокруткой скроллбара
    Скрытие элемента перелистыванием TabPage
 - работает, однако возможны ошибки, так что имейте ввиду.

Код

public static class ReallyVisibility
    {
        public static bool Visible(Control control)
        {
            if (!control.Visible)
                return false; //если Visible == false, то и проверять нечего

            List<Control> parentList = GetComponentTree(control);
            foreach (Control controlInTree in parentList)
            {
                if (!ChildVisibleRespectParent(controlInTree))
                    return false;
            }

            return true;
        }

        private static List<Control> GetComponentTree(Control child)
        {
            List<Control> parentList = new List<Control>();
            parentList.Add(child);

            Control parent = child.Parent;
            while (parent != null)
            {
                parentList.Add(parent);
                parent = parent.Parent;
            }
            parentList.Reverse();
            return parentList;
        }

        //Видимость child-а относительно его родителя
        private static bool ChildVisibleRespectParent(Control child)
        {
            if (!child.Visible)
                return false; //если Visible == false, то и проверять нечего

            Control parent = child.Parent;
            if (parent == null)
                return child.Visible;


            Point childScreenPoint = child.PointToScreen(Point.Empty);
            Point pos = parent.PointToClient(childScreenPoint);
            List<Point> childPointList = GetChildKeyPoints(child, pos);

            foreach (Point childPoint in childPointList)
            {
                Control childAtPoint = parent.GetChildAtPoint(childPoint);

                #region parent is TabControl?
                //Выход из ситуации, когда при любом tabControl.SelectedIndex 
                //tabControl.GetChildAtPoint всегда возвращает tabControl.TabPages[0]
                if (parent is TabControl)
                {
                    TabControl tabControl = (TabControl)parent;
                    if (tabControl.TabPages.Count != 0 && childAtPoint == tabControl.TabPages[0] && tabControl.SelectedIndex != 0)
                    {
                        childAtPoint = tabControl.SelectedTab;
                    }
                }
                #endregion

                if (childAtPoint == child)
                    return true;
            }

            return false;
        }

        //Какие точки будем проверять?
        private static List<Point> GetChildKeyPoints(Control child, Point pos)
        {
            List<Point> childPointList = new List<Point>();

            #region Проверка для "прямоугольных" компонентов
            childPointList.Add(pos); //левый верхний угол
            childPointList.Add(new Point(pos.X + child.Width - 1, pos.Y)); //правый верхний угол
            childPointList.Add(new Point(pos.X, pos.Y + child.Height - 1)); //нижний левый угол
            childPointList.Add(new Point(pos.X + child.Width - 1, pos.Y + child.Height - 1)); //правый нижний угол
            #endregion

            #region Проверка для компонентов другой формы (овал может быть?)
            childPointList.Add(new Point(pos.X + child.Width / 3, pos.Y + child.Height / 3)); //левый верхний угол
            childPointList.Add(new Point(pos.X + child.Width / 2, pos.Y + child.Height / 2)); //середина
            childPointList.Add(new Point(pos.X + child.Width / 3 * 2, pos.Y + child.Height / 3 * 2)); //правый нижний угол
            #endregion

            return childPointList;
        }


Как пользоваться:
Код

bool reallyVisible = ReallyVisibility.Visible(textBox1);

Автор: Экскалупатор 20.7.2011, 18:31
Цитата(elsan @  20.7.2011,  11:09 Найти цитируемый пост)
Вариант ловить событие изменения вкладок не желателен.

интересно чем вызвано подобное ограничение? вполне логично было бы считать что если таб не активен то и контролы не видны...

Автор: elsan 21.7.2011, 07:13
Спасибо большое за конкретную реализацию. smile Сейчас буду пробовать применить.
Цитата

интересно чем вызвано подобное ограничение? вполне логично было бы считать что если таб не активен то и контролы не видны...

Да верно, но компоненты которые используются для построения - UserControl, и хотелось бы чтобы все свойства и события были у них универсальными насколько возможно, а не привязывались к конкретной задаче. Планируется сделать свою библиотеку. 

Спасибо за быстрый ответ.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)