【问题标题】:C# Modify Form Size during SizeChanged EventC# 在 SizeChanged 事件期间修改表单大小
【发布时间】:2015-07-10 01:16:09
【问题描述】:

如果满足条件,我会在调整表单大小时尝试设置表单的高度。我将其设置为仅允许使用 code provided by in this answer 手动更改表单的宽度。

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

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

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

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

【问题讨论】:

    标签: c# winforms resize


    【解决方案1】:

    但是,在我的 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;
            }
        }
    
    }
    

    【讨论】:

    • 这很有趣。我决定再试一次,然后看看我是否在这里有任何答案,而我想出的解决方案正是这个!当我看到你这样做时,我正要回答我自己的问题,所以我会接受你的回答。谢谢!
    【解决方案2】:

    试试这个:

    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
    }
    

    【讨论】:

    • 这不起作用。我决定采用@Idle_Mind 的解决方案。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-18
    • 2018-04-13
    • 2011-04-26
    • 1970-01-01
    • 2020-03-30
    相关资源
    最近更新 更多