UFO ET IT

C # 폼에서 컨트롤의 위치 가져 오기

ufoet 2020. 11. 20. 17:25
반응형

C # 폼에서 컨트롤의 위치 가져 오기


컨트롤이 다른 컨트롤 (예 : 패널) 안에있을 수있는 경우 폼에서 컨트롤의 위치를 ​​검색하는 방법이 있습니까?

컨트롤의 Left 및 Top 속성은 부모 컨트롤 내의 위치 만 제공하지만 내 컨트롤이 5 개의 중첩 된 패널 내에 있고 폼에서 위치가 필요한 경우 어떻게해야합니까?

빠른 예 :

btnA 버튼은 패널 pnlB 내부의 좌표 (10,10)에 있습니다.
패널 pnlB는 frmC 양식 내의 좌표 (15,15)에 있습니다.

나는 frmC에서 btnA의 위치를 ​​원합니다. (25,25)

이 위치를 얻을 수 있습니까?


나는 보통 다음 PointToScreenPointToClient같이 결합합니다 .

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

controls PointToScreen메서드를 사용 하여 화면에 대한 절대 위치를 얻을 수 있습니다.

Forms PointToScreen메서드를 수행하고 기본 수학으로 컨트롤의 위치를 ​​가져올 수 있습니다.


보통 이렇게 해요 .. 매번 일 해요 ..

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

양식에 도착할 때까지 부모를 통해 부모 내에서의 위치를 ​​기록 할 수 있습니다.

편집 : (예상되지 않음) :

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;
}

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은 내 상황에 적합하지 않았습니다. 특히 어떤 양식과도 연결되지 않은 오프 스크린 컨트롤로 작업하고 있기 때문입니다. 나는 sahin의 솔루션이 가장 도움이되는 것을 발견했지만 재귀를 제거하고 Form 종료를 제거했습니다. 아래 솔루션은 IContainered 여부에 관계없이 표시되거나 표시되지 않는 모든 컨트롤에 대해 작동합니다. 감사합니다 Sahim.

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;
}

내 테스트에서 Hans Kesting과 Fredrik Mörk의 솔루션 모두 동일한 답을 제공했습니다. 그러나:

Raj More와 Hans Kesting의 방법을 사용하여 답변에서 흥미로운 불일치를 발견하고 공유 할 것이라고 생각했습니다. 도움을 주신 두 분 모두에게 감사드립니다. 그러한 방법이 프레임 워크에 내장되어 있지 않다는 것을 믿을 수 없습니다.

Raj는 코드를 작성하지 않았으므로 내 구현이 그가 의도 한 것과 다를 수 있습니다.

내가 찾은 차이점은 Raj More의 방법이 Hans Kesting의 방법보다 X와 Y 모두에서 종종 2 픽셀 더 크다는 것입니다. 나는 이것이 왜 발생하는지 아직 결정하지 못했습니다. Windows 양식 내용 주위에 2 픽셀 테두리가있는 것처럼 보이는 사실과 관련이 있다고 확신합니다 (예 : 양식의 가장 바깥 쪽 테두리 내부). 확실히 어느 정도까지 철저하지 않은 내 테스트에서 중첩 된 컨트롤에서만이를 발견했습니다. 그러나 모든 중첩 된 컨트롤이이를 표시하는 것은 아닙니다. 예를 들어, 불일치를 나타내는 GroupBox 내부에 TextBox가 있지만 동일한 GroupBox 내부의 Button은 그렇지 않습니다. 이유를 설명 할 수 없습니다.

답변이 동등 할 때 그들은 (0, 0) 점이 위에서 언급 한 내용 테두리 안에 있는 것으로 간주합니다 . 따라서 저는 Hans Kesting과 Fredrik Mörk의 솔루션이 옳다고 생각할 것이라고 생각하지만 제가 Raj More 's를 구현 한 솔루션을 믿을 수는 없다고 생각합니다.

또한 Raj More가 아이디어를 제공했지만 코드를 제공하지 않았기 때문에 정확히 어떤 코드를 작성했는지 궁금했습니다. 이 게시물을 읽을 때까지 PointToScreen () 메서드를 완전히 이해하지 못했습니다. http://social.msdn.microsoft.com/Forums/en-US/netfxcompact/thread/aa91d4d8-e106-48d1-8e8a-59579e14f495

테스트 방법은 다음과 같습니다. 주석에 언급 된 '방법 1'은 Hans Kesting과 약간 다릅니다.

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);
        }

참고URL : https://stackoverflow.com/questions/1478022/c-sharp-get-a-controls-position-on-a-form

반응형