Изменение размера формы только на определенные размеры

#c# #winforms #resize #window-resize

#c# #winforms #изменение размера #окно-изменение размера

Вопрос:

Я хочу разрешить любую высоту формы, но только определенную ширину (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 ... 
};
  

Когда я пытаюсь изменить размер своей формы, граница колеблется между положением мыши и ожидаемой шириной. Как я могу добиться такого поведения?

Ответ №1:

Я думаю, проблема в том, что вы делаете это в Resize событии, поэтому, как только мышь начинает двигаться, событие срабатывает, и ваш код изменяет размер формы.

Вместо этого попробуйте использовать ResizeEnd событие, которое срабатывает только после того, как пользователь прекращает изменять размер:

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

Комментарии:

1. Вот так. Прошло некоторое время с тех пор, как я работал в Winforms

2. Почти решение. Было бы лучше, если бы форма резко изменялась с 300 пикселей до 550 пикселей, с 1 столбца данных до 2 столбцов фиксированного размера

3. Я думал, что это то, что ваш код уже сделал, но вы не хотели, чтобы он изменялся? Пожалуйста, проясните вопрос. Что не работает с вашим кодом, и какое поведение вы хотите видеть вместо этого?

4. «Я думал, что это то, что ваш код уже сделал, но вы не хотели, чтобы он изменялся?». Да, это так.

Ответ №2:

Изменение размера или событие BeforeResize для формы

Для управления размером формы, ResizeEnd или SizeChanged немного запаздывают, и если вы хотите изменить размер в этих событиях, это приводит к мерцанию.

Чтобы обработать изменение размера до применения нового размера, вы можете отправить сообщение WM-SIZING, которое включает предлагаемый размер и край формы, который вызвал изменение размера.

В следующем примере я установил размер плитки для формы и попытался изменить размер на основе плиток:

введите описание изображения здесь

 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);
}