C#在SizeChanged事件期间修改表单大小

时间:2015-07-10 01:16:10

标签: c# winforms resize

如果符合条件,我正在尝试设置表单的高度,而我正在调整表单的高度。我将其设置为仅允许使用this link手动更改表单的宽度。

我有一个FlowLayoutPanel,显示一组PictureBox控件,每个控件都有一个50像素的固定高度。最初,表单的高度为38(Size.Height - ClientSize.Height)+ 50 + 6(Margin.Top + Margin.Bottom of image)= 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事件中调用时,此方法会导致Form在初始高度和新高度之间“闪烁”:

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

我猜是因为设置Height会再次触发SizeChange事件,但我不知道如何解决这个问题。在设置高度后打印出lastElement.Bottom + lastElement.Margin.BottomitemPanel.Height的值时,它们是相同的,但代码仍然以某种方式达到了这一点。

简而言之,我希望表单宽度手动更改,但是在添加项目或更改宽度时要更改的表单高度,这样就可以查看FlowLayoutPanel中的所有控件。

2 个答案:

答案 0 :(得分:0)

  

但是,在我的SizeChange事件中调用时,此方法会导致   表格到&#34; flash&#34;在初始高度和新高度之间

基本上任何股票&#34;调整大小&#34;您的表格的事件发生得太晚,您无法在不明显的情况下更改大小。

您想要捕获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 :(得分:-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
}