2014-12-30 44 views
2

在我的應用程序中,我遇到了以下情況:可滾動區域如何檢索顯示內容的大小?

我有一個帶有多個選項卡的選項卡控件的Windows窗體。每個選項卡包含任意內容,在啓動時或運行時由其他類添加。

我想以一種方式設置選項卡,只要窗體太小而不能讓選項卡的面板顯示所有內容,滾動條就會自動顯示。

我到目前爲止試過的是設置標籤頁的AutoScroll = true並將AutoScrollMinSize屬性設置爲面板的大小。

由於面板的Size似乎總是(200,100)獨立於其內容,所以沒有按預期工作。

我創建了一個小示例應用程序(代碼如下),它演示了這個問題。如果調整窗體大小,只有當窗體小於面板(默認大小爲(200,100))而不是面板中的文本框(大小爲300,150)時纔會顯示滾動條。如果手動設置AutoScrollMinSize(取消註釋第34行),則表現如預期。

問題是:標籤頁如何檢索顯示內容的實際大小?

我大概可以通過所有控件進行遞歸,並嘗試自己計算大小 - 但這種感覺真的很糟糕。 PS:請不要建議將面板的大小設置爲標籤的大小,因爲實際面板比這更復雜。 ;-)


代碼:

在Visual Studio只需創建一個應用程序,並用下面的代碼替換Program.cs中:

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回報率(200,100)。在您的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(...)方法。除非AutoSize爲真,否則將不會調用GetPreferredSize(...)

如果你談論的是一個普通的PanelUserControl,默認情況下這些使用所見即所得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

相關問題