2015-07-10 826 views
0

我試圖在調整窗體大小時設置窗體高度,如果條件滿足。我已將它設置爲只允許使用code provided by in this answer手動更改表單的寬度。C#在SizeChanged事件中修改窗體大小事件

我有一個FlowLayoutPanel顯示一組PictureBox控件,每個控件都有一個50像素的固定高度。最初,表單的高度爲38(Size.Height - ClientSize.Height)+ 50 + 6(圖像的邊距。頂部+邊距.Bottom)= 94。

如果控件溢出,默認情況下,FlowLayoutPanel將它們推送下到一個新的線。我想要做的是在發生這種情況時調整窗體大小,或者手動更改窗體寬度,這可能會導致控件跳到下一行。

下面的代碼工作,每當一個新的控件添加到FlowLayoutPanel的(itemPanel)被稱爲:

private void ResizeForm() 
{ 
    if (itemPanel.Controls.Count < 1) return; 

    var lastElement = itemPanel.Controls[itemPanel.Controls.Count - 1]; 

    // The Form is the correct size, no need to resize it: 
    if (lastElement.Bottom + lastElement.Margin.Bottom == itemPanel.Height) return; 

    Height = 38 + lastElement.Bottom + lastElement.Margin.Bottom; 
} 

然而,當我SizeChange事件中調用,這種方法會使表單「閃」最初的高度和新的高度之間:

private void MainForm_SizeChanged(object sender, EventArgs e) 
{ 
    ResizeForm(); 
} 

我猜測的原因是因爲安裝高度將再次觸發SizeChange事件,但我不知道如何解決這個問題。設置高度後,當我打印出lastElement.Bottom + lastElement.Margin.BottomitemPanel.Height的值時,它們是相同的,但代碼仍然以某種方式達到該點。

概括地說,我想表格寬度是手動改變,但形式的高度改變時,添加項目或寬度改變,從而使FlowLayoutPanel的內部的所有控件可以查看。

回答

0

然而,當我SizeChange事件中調用此方法將導致 表單中的初始高度和新的高度之間「閃」

基本上,任何股票「調整大小」事件爲您的形式將發生太晚,您可以更改大小,而不會引人注意。

你要陷阱WM_SIZING消息:

發送到用戶調整窗口大小。通過處理此消息,應用程序可以監視矩形的拖動大小和位置,並在需要時更改其大小或位置。

這將讓你實際上已經更新,在屏幕上之前更改表單的大小。

這將是這個樣子:

public partial class Form1 : Form 
{ 

    private struct RECT 
    { 
     public int Left; 
     public int Top; 
     public int Right; 
     public int Bottom; 
    } 

    enum HitTest 
    { 
     Caption = 2, 
     Transparent = -1, 
     Nowhere = 0, 
     Client = 1, 
     Left = 10, 
     Right = 11, 
     Top = 12, 
     TopLeft = 13, 
     TopRight = 14, 
     Bottom = 15, 
     BottomLeft = 16, 
     BottomRight = 17, 
     Border = 18 
    } 

    private const int WM_SIZING = 0x214; 
    private const int WM_NCHITTEST = 0x84; 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    protected override void WndProc(ref Message m) 
    { 
     base.WndProc(ref m); 

     switch (m.Msg) 
     { 
      case WM_NCHITTEST: 
       var result = (HitTest)m.Result.ToInt32(); 
       if (result == HitTest.Top || result == HitTest.Bottom) 
        m.Result = new IntPtr((int)HitTest.Caption); 
       if (result == HitTest.TopLeft || result == HitTest.BottomLeft) 
        m.Result = new IntPtr((int)HitTest.Left); 
       if (result == HitTest.TopRight || result == HitTest.BottomRight) 
        m.Result = new IntPtr((int)HitTest.Right); 
       break; 

      case WM_SIZING: 
       // Retrieve the "proposed" size of the Form in "rc": 
       RECT rc = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT)); 

       // ... do something with "rc" ... 

       // this is your code (slightly modified): 
       if (itemPanel.Controls.Count > 0) 
       { 
        var lastElement = itemPanel.Controls[itemPanel.Controls.Count - 1]; 

        if (lastElement.Bottom + lastElement.Margin.Bottom != itemPanel.Height) 
        { 
         int Height = 38 + lastElement.Bottom + lastElement.Margin.Bottom; 
         rc.Bottom = rc.Top + Height; // <--- use "Height" to update the "rc" struct 
        } 
       } 

       // Put the updated "rc" back into message structure: 
       Marshal.StructureToPtr(rc, m.LParam, true); 
       break; 
     } 
    } 

} 
+1

這很搞笑。我決定在看到這裏有沒有答案之前再試一次,我提出的解決方案就是這個!當我看到你這樣做時,我正要回答自己的問題,所以我會接受你的回答。謝謝! – driima

-1

試試這個:

private void ResizeForm() 
{ 
    this.SuspendLayout(); // Suspends the layout logic until ResumeLayout() is called (below) 

    if (itemPanel.Controls.Count < 1) return; 

    var lastElement = itemPanel.Controls[itemPanel.Controls.Count - 1]; 

    // The Form is the correct size, no need to resize it: 
    if (lastElement.Bottom + lastElement.Margin.Bottom == itemPanel.Height) return; 

    Height = 38 + lastElement.Bottom + lastElement.Margin.Bottom; 

    this.ResumeLayout(); // ADD THIS AS WELL 
} 
+0

這是行不通的。我決定採用@ Idle_Mind的解決方案。謝謝 – driima