2014-12-30 1 views
2

내 응용 프로그램에서 다음 상황이 발생했습니다.스크롤 영역에서 표시되는 크기를 검색하는 방법은 무엇입니까?

여러 탭이있는 탭 컨트롤이있는 Windows Form이 있습니다. 각 탭에는 시작시 또는 런타임 중에 다른 클래스에 의해 추가되는 임의의 내용이 들어 있습니다.

폼을 탭의 패널이 모든 것을 표시하기에 너무 작아지면 스크롤바가 자동으로 표시되는 방식으로 탭을 설정하려고합니다.

지금까지 시도한 것은 탭 페이지의 AutoScroll = true을 설정하고 AutoScrollMinSize 속성을 패널 크기로 설정하는 것입니다.

패널의 Size은 항상 내용에 독립적 (200, 100) 인 것으로 예상되어 예상대로 작동하지 않았습니다.

문제를 설명하는 작은 예제 응용 프로그램 (아래 코드)을 만들었습니다. 양식의 크기를 조정하면 양식이 패널 (300, 150 크기)의 텍스트 상자가 아닌 패널 (기본 크기는 (200, 100))보다 작아 진 경우에만 스크롤 막대가 표시됩니다. AutoScrollMinSize을 수동으로 설정하면 (줄 34의 주석 처리 제외) 예상대로 작동합니다.

질문 : 탭 페이지에 표시되는 내용의 실제 크기를 검색하려면 어떻게해야합니까?

나는 모든 컨트롤을 통해 반복적으로 크기를 계산할 수 있지만 실제로는 좋지 않습니다.

추 신 : 실제 패널은 훨씬 더 복잡하기 때문에 패널 크기를 레이블 크기로 설정하지 마십시오. ;-)


코드 :

단순히 Visual Studio에서 응용 프로그램을 만들고 다음 코드를 Program.cs를 오버라이드 (override) :

using System; 
using System.Windows.Forms; 

namespace ScrollbarTest 
{ 
    static class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 

      var sampleForm = CreateSampleForm(); 

      Application.Run(sampleForm); 
     } 

     private static Form CreateSampleForm() 
     { 
      var sampleForm = new Form() { }; 
      var tabControl = new TabControl() { Dock = DockStyle.Fill }; 
      var tabPage = new TabPage("Test") { AutoScroll = true }; 
      sampleForm.Controls.Add(tabControl); 
      tabControl.TabPages.Add(tabPage); 

      var samplePanel = CreateSamplePanel(); 
      tabPage.Controls.Add(samplePanel); 

      // this does not provide the right size 
      tabPage.AutoScrollMinSize = samplePanel.Size; 

      // uncomment this to make it work 
      //tabPage.AutoScrollMinSize = new System.Drawing.Size(300, 150); 

      return sampleForm; 
     } 

     private static Control CreateSamplePanel() 
     { 
      // As an example, create a panel with a text box with a fixed size. 
      var samplePanel = new Panel() { Dock = DockStyle.Fill }; 
      var sampleSize = new System.Drawing.Size(300, 150); 
      var textBox = new TextBox() 
      { 
       Dock = DockStyle.Fill, 
       MinimumSize = sampleSize, 
       MaximumSize = sampleSize, 
       Size = sampleSize 
      }; 
      samplePanel.Controls.Add(textBox); 

      return samplePanel; 
     } 
    } 
} 
+0

탭 페이지에 포함 된 패널에 대해 알지 못합니다. 대신 패널에서 스크롤 막대를 설정하지 마십시오. –

+0

그런 경우 패널에서 같은 문제가 발생합니다. 패널은 일반적으로 여러 컨트롤이있는 여러 개의 하위 패널이있는 TableLayoutPanel로 구성됩니다. –

답변

1

samplePanel.Size 반환 (200100). CreateSamplePanel 메서드에서 samplePanel.MinimumSize = sampleSize;을 설정하면 코드가 작동합니다.

패널은 하위 컨트롤을 기반으로 크기 속성 (예 : Size, MinimumSize, PreferredSize)을 계산하지 않습니다. Panel을 서브 클래스 화하고 그 동작을 제공해야합니다. TableLayoutPanelFlowLayoutPanel도 정확하게 PreferredSize 속성을 계산하지 않습니다. 이는 놀랍습니다. 최소한 일반적으로 GetPreferredSize(Size proposedSize) 메서드를 재정의하고 MinimumSize 속성의 경우 PreferredSize 속성을 반환하도록 할 수도 있습니다.

DockStyle.FillMinimumSize은 서로 상반됩니다. TabPage 컨트롤은 본질적으로 DockStyle.Fill 모드이므로 AutoScrollMinSize 속성을 설정해야합니다.

편집 : 컨트롤 목록의 총 필요한 크기를 (재귀 적으로) 검색하는 기존 기능이 없습니다 (예 : X/Y 및 크기를 통해?

호스트 컨테이너 자체 (예 :TableLayoutPanel) 정확히 그 레이아웃을 수행하는 방법의 정확한 정보를 알고 있기 때문에 해당 PreferredSize 올바르게 계산할 수 있습니다.

AutoSize 속성을 true로 설정하고 GetPreferredSize(...)/PreferredSize이 올바른 크기로 계산되기를 바랍니다. TableLayoutPanel의 경우 올바르게 계산되지 않은 경우가 있었고 하위 클래스를 작성하여 GetPreferredSize(...) 메서드를 재정의해야한다는 것을 상기합니다. GetPreferredSize(...)AutoSize이 참일 때까지 호출되지 않습니다.

일반 Panel 또는 UserControl에 대해 이야기하는 경우 기본값으로 WYSIWYG LayoutEngine을 사용하고 PreferredSize은 계산하지 마십시오. 당신은 서브 클래스화할 수 있고 최대 값은 control.X + control.Width이고 높이는 같은 것을 계산하여 기본 크기로 사용하십시오.

먼저 AutoSize을 true로 설정하고 해당 설정이 작동하는지 확인하십시오. 그렇지 않은 경우 GetPreferredSize(...) 메소드를 재정의해야 할 수 있습니다. 다음은 원산지 예입니다.

[STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 

     var sampleForm = new Form() { AutoScroll = true }; 

     var panel = new MyPanel() { AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink, BackColor = Color.LightYellow }; 

     for (int i = 0; i < 6; i++) { 
      for (int j = 0; j < 3; j++) { 
       Button b = new Button { Text = "Button" + panel.Controls.Count, AutoSize = true }; 
       b.Click += delegate { 
        MessageBox.Show("Preferred Size: " + panel.PreferredSize); 
       }; 
       panel.Controls.Add(b, j, i); 
      } 
     } 

     sampleForm.Controls.Add(panel); 
     Application.Run(sampleForm); 
    } 

    private class MyPanel : TableLayoutPanel { 
     public override Size MinimumSize { 
      get { 
       return PreferredSize; 
      } 
      set { 

      } 
     } 

     public override Size GetPreferredSize(Size proposedSize) { 
      Size s = new Size(); 
      int[] harr = new int[100];//this.RowCount]; 
      int[] warr = new int[100];//this.ColumnCount]; 
      foreach (Control c in this.Controls) { 
       var cell = this.GetPositionFromControl(c); 
       var ps = c.PreferredSize; 
       Padding m = c.Margin; 
       int w = ps.Width + m.Horizontal; 
       int h = ps.Height + m.Vertical; 
       if (w > warr[cell.Column]) 
        warr[cell.Column] = w; 
       if (h > harr[cell.Row]) 
        harr[cell.Row] = h; 
      } 

      foreach (int w in warr) 
       s.Width += w; 
      foreach (int h in harr) 
       s.Height += h; 

      return s; 
     } 
    } 
+0

실제 응용 프로그램에있는 것은 'sampleSize'가 없습니다. 컨트롤 목록의 총 필요한 크기를 (재귀 적으로) 검색하는 기존 함수가 없습니다 (예 : X/Y 및 크기를 통해? –

+0

수정 된 질문에 대한 답변보기 – Loathing

관련 문제