仅按特定尺寸调整表格
Resize form by only specific sizes
我想允许任何表单高度,但只允许特定宽度(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 的调整大小或 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);
}
我想允许任何表单高度,但只允许特定宽度(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 的调整大小或 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);
}