C# получить позицию элемента управления в форме



есть ли способ получить положение элемента управления в форме, когда элемент управления может находиться внутри других элементов управления (например, панелей)?



левые и верхние свойства элемента управления дают мне только его позицию в родительском элементе управления, но что делать, если мой элемент управления находится внутри пяти вложенных панелей, и мне нужна его позиция в форме?



пример:



кнопка btnA расположена по координатам (10,10) внутри панели pnlB.

Панель pnlB расположена на координаты (15,15) внутри формы frmC.



Я хочу, чтобы местоположение btnA на frmC, которое составляет (25,25).



могу ли я получить это место?

1422   9  

9 ответов:

Я обычно совмещают PointToScreen и PointToClient:

Point locationOnForm = control.FindForm().PointToClient(
    control.Parent.PointToScreen(control.Location));

Вы можете использовать элементы управления PointToScreen метод, чтобы получить абсолютное положение относительно экрана.

Вы можете сделать формы PointToScreen метод, и с основной математикой, получить положение элемента управления.

вы можете пройти через родителей, отмечая их положение внутри своего родителя, пока не дойдете до формы.

правка: что-то вроде (непроверенных):

public Point GetPositionInForm(Control ctrl)
{
   Point p = ctrl.Location;
   Control parent = ctrl.Parent;
   while (! (parent is Form))
   {
      p.Offset(parent.Location.X, parent.Location.Y);
      parent = parent.Parent;
   }
   return p;
}

Я обычно делаю так.. Работает каждый раз..

var loc = ctrl.PointToScreen(Point.Empty);

Supergeek, ваша нерекурсивная функция не привела к правильному результату, но моя делает. Я считаю, что ваш делает слишком много дополнений.

private Point LocationOnClient(Control c)
{
   Point retval = new Point(0, 0);
   for (; c.Parent != null; c = c.Parent)
   { retval.Offset(c.Location); }
   return retval;
}

Как ни странно, PointToClient и PointToScreen не были идеальными для моей ситуации. Особенно потому, что я работаю с закадровыми элементами управления, которые не связаны с какой-либо формой. Я нашел решение Сахина наиболее полезным, но вынул рекурсию и устранил завершение формы. Решение ниже работает для любого из моих элементов управления, видимых или нет, содержащихся в форме или нет, IContainered или нет. Благодаря Его Видела.

private static Point FindLocation(Control ctrl)
{
    Point p;
    for (p = ctrl.Location; ctrl.Parent != null; ctrl = ctrl.Parent)
        p.Offset(ctrl.Parent.Location);
    return p;
}

в моем тестировании решения Ганса Кестинга и Фредрика Мерка дали один и тот же ответ. Но:

Я нашел интересное несоответствие в ответе, используя методы Раджа Мора и Ганса Кестинга, и подумал, что поделюсь. Спасибо хоть за помощь; я не могу поверить, что такой метод не встроен в платформу.

обратите внимание, что Радж не писал код, и поэтому моя реализация может отличаться от того, что он имел в виду.

разница I оказалось, что метод из Raj More часто будет на два пикселя больше (как в X, так и в Y), чем метод из Hans Kesting. Я еще не определил почему это происходит. Я почти уверен, что это как-то связано с тем, что вокруг содержание формы Windows (например, внутри внешних границ формы). В моем тестировании, которое, безусловно, не было исчерпывающим в какой-либо степени, я столкнулся с ним только на вложенных элементах управления. Однако, не все вложенные элементы управления показывают его. Например, у меня есть текстовое поле внутри группового поля, которое показывает несоответствие, но кнопка внутри того же группового поля не делает. Я не могу объяснить, почему.

обратите внимание, что когда ответы эквивалентны, они считают точку (0, 0)внутри граница содержания, о которой я упоминал выше. Поэтому я считаю, что я буду считать решения от Ханса Кестинга и Фредрика Мерка правильными, но не думаю, что я буду доверять решению, которое у меня есть реализовано Раджа Мора.

мне также было интересно, какой именно код написал бы Радж Мор, так как он дал идею, но не предоставил код. Я не полностью понял метод PointToScreen (), пока не прочитал этот пост: http://social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/aa91d4d8-e106-48d1-8e8a-59579e14f495

вот мой метод для тестирования. Обратите внимание, что "метод 1", упомянутый в комментариях, немного отличается от Hans Кестинг это.

private Point GetLocationRelativeToForm(Control c)
{
  // Method 1: walk up the control tree
  Point controlLocationRelativeToForm1 = new Point();
  Control currentControl = c;
  while (currentControl.Parent != null)
  {
    controlLocationRelativeToForm1.Offset(currentControl.Left, currentControl.Top);
    currentControl = currentControl.Parent;
  }

  // Method 2: determine absolute position on screen of control and form, and calculate difference
  Point controlScreenPoint = c.PointToScreen(Point.Empty);
  Point formScreenPoint = PointToScreen(Point.Empty);
  Point controlLocationRelativeToForm2 = controlScreenPoint - new Size(formScreenPoint);

  // Method 3: combine PointToScreen() and PointToClient()
  Point locationOnForm = c.FindForm().PointToClient(c.Parent.PointToScreen(c.Location));

  // Theoretically they should be the same
  Debug.Assert(controlLocationRelativeToForm1 == controlLocationRelativeToForm2);
  Debug.Assert(locationOnForm == controlLocationRelativeToForm1);
  Debug.Assert(locationOnForm == controlLocationRelativeToForm2);

  return controlLocationRelativeToForm1;
}
private Point FindLocation(Control ctrl)
{
    if (ctrl.Parent is Form)
        return ctrl.Location;
    else
    {
        Point p = FindLocation(ctrl.Parent);
        p.X += ctrl.Location.X;
        p.Y += ctrl.Location.Y;
        return p;
    }
}

Это то, что я сделал работает как шарм

            private static int _x=0, _y=0;
        private static Point _point;
        public static Point LocationInForm(Control c)
        {
            if (c.Parent == null) 
            {
                _x += c.Location.X;
                _y += c.Location.Y;
                _point = new Point(_x, _y);
                _x = 0; _y = 0;
                return _point;
            }
            else if ((c.Parent is System.Windows.Forms.Form))
            {
                _point = new Point(_x, _y);
                _x = 0; _y = 0;
                return _point;
            }
            else 
            {
                _x += c.Location.X;
                _y += c.Location.Y;
                LocationInForm(c.Parent);
            }
            return new Point(1,1);
        }

Comments

    Ничего не найдено.