仅按特定大小调整表格大小

问题描述

我想允许任何形式的高度,但只允许特定的宽度(300、550、800,...(+ 250))。我尝试了这段代码

Resize += (s,a) => {
    if (Width < 425)
        Width = 300;
    else if (Width < 675)
        Width = 550;
    else if (Width < 925)
        Width = 800;
    else ... 
};

当我尝试调整表单大小时,边框在鼠标位置和预期宽度之间波动。我该如何实现这种行为?

解决方法

我认为问题在于您正在Resize事件中执行此操作,因此,一旦鼠标开始移动,事件就会触发,并且您的代码会调整表单的大小。

相反,请尝试使用ResizeEnd事件,该事件仅在用户停止调整大小后才触发:

ResizeEnd += (s,a) =>
{
    var widths = new[] {300,550,800,1050,1300,1550,1800};
    Width = widths.First(w => Width < w + 125);
};
,

Form 的 Sizing 或 BeforeResize 事件

为了控制表单的大小,ResizeEnd 或 SizeChanged 有点晚,如果您想在这些事件中更改大小,则会导致闪烁。

要在应用新尺寸之前处理尺寸,您可以处理 WM-SIZING 消息,其中包括建议尺寸和触发调整尺寸的表单边缘。

在以下示例中,我为表单设置了磁贴大小并尝试根据磁贴调整大小:

enter image description here

private int widthGridSize = 200;
private int heightGridSize = 1;

private const int WM_SIZING = 0x0214;
enum EdgeType : int
{
    WMSZ_LEFT = 1,WMSZ_RIGHT = 2,WMSZ_TOP = 3,WMSZ_TOPLEFT = 4,WMSZ_TOPRIGHT = 5,WMSZ_BOTTOM = 6,WMSZ_BOTTOMLEFT = 7,WMSZ_BOTTOMRIGHT = 8
}
[StructLayout(LayoutKind.Sequential)]
public class RECT
{
    public int L,T,R,B;
    public int W => R - L;
    public int H => B - T;
}
protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_SIZING)
    {
        var flag = (EdgeType)m.WParam;
        var rect = new RECT();
        Marshal.PtrToStructure(m.LParam,rect);
        var w = (int)Math.Round((double)rect.W / widthGridSize) * widthGridSize;
        var h = (int)Math.Round((double)rect.H / heightGridSize) * heightGridSize;
        switch (flag)
        {
            case EdgeType.WMSZ_LEFT:
                rect.L = rect.R - w;
                break;
            case EdgeType.WMSZ_RIGHT:
                rect.R = rect.L + w;
                break;
            case EdgeType.WMSZ_TOP:
                rect.T = rect.B - h;
                break;
            case EdgeType.WMSZ_TOPLEFT:
                rect.T = rect.B - h;
                rect.L = rect.R - w;
                break;
            case EdgeType.WMSZ_TOPRIGHT:
                rect.T = rect.B - h;
                rect.R = rect.L + w;
                break;
            case EdgeType.WMSZ_BOTTOM:
                rect.B = rect.T + h;
                break;
            case EdgeType.WMSZ_BOTTOMLEFT:
                rect.B = rect.T + h;
                rect.L = rect.R - w;
                break;
            case EdgeType.WMSZ_BOTTOMRIGHT:
                rect.B = rect.T + h;
                break;
            default:
                break;
        }
        Marshal.StructureToPtr(rect,m.LParam,true);
        m.Result = (IntPtr)1;
    }
    else
        base.WndProc(ref m);
}