将窗口大小捕捉到固定倍数

本文关键字:窗口大小 | 更新日期: 2023-09-27 18:21:33

Windows命令控制台只允许将窗口大小调整为字符大小的倍数。窗口大小的这种"捕捉"是即时的,不会闪烁。在本机代码中,这是通过处理WM_SIZING消息并相应地修改RECT结构来完成的。

在C#中,我尝试重写OnResize方法,计算"快照"大小,并相应地设置Form的ClientSize属性。不幸的是,大小一直在捕捉的大小和光标当前指定的任何大小之间跳跃。

protected override void OnResize(EventArgs e)
{
    int tgtCols = (ClientSize.Width + 4) / 8;
    int tgtLines = (ClientSize.Height + 8) / 15;
    if (cols != tgtCols || lines != tgtLines)
    {
        cols = tgtCols;
        lines = tgtLines;
        int tgtWidth = cols * 8;
        int tgtHeight = lines * 15;
        //ClientSize = new Size(tgtWidth, tgtHeight);
        Size = new Size(tgtWidth + exWidth, tgtHeight + exHeight);
    }
    base.OnResize(e);
}

正如您所看到的,我已经尝试使用SizeClientSize属性,但两者都会产生相同的效果。有没有更好的方法来限制尺寸?还是需要手动拦截WM_SIZING消息?

EDIT:我也尝试手动拦截WM_SIZING,但我得到了相同的结果:

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case WM_SIZING:
            DoSizeSnap(ref m);
            m.Result = new IntPtr(1);
            break;
        default:
            base.WndProc(ref m);
            break;
    }
}
private unsafe void DoSizeSnap(ref Message m)
{
    int edge = m.WParam.ToInt32();
    RECT *pRect = (RECT *)m.LParam.ToPointer();
    int tgtCols = (pRect->right - pRect->left - exWidth + 4) / 8;
    int tgtLines = (pRect->bottom - pRect->top - exHeight + 8) / 15;
    if (cols != tgtCols || lines != tgtLines)
    {
        cols = tgtCols;
        lines = tgtLines;
        int tgtWidth = cols * 8;
        int tgtHeight = lines * 15;
        // TODO: handle edge
        pRect->right = pRect->left + tgtWidth + exWidth;
        pRect->bottom = pRect->top + tgtHeight + exHeight;
    }
}

订阅Resize事件也不起作用。

将窗口大小捕捉到固定倍数

问题在于语句if (cols != tgtCols || lines != tgtLines)。这将导致只有当目标行/列发生更改时才进行大小捕捉,而当窗口宽度/高度发生更改时,不会。这是为了防止无限递归,但如果大小实际上没有改变,则不会触发Resize事件,因此if语句是不必要的。