调整无边框窗口右下角大小

16

我希望用户能够像调整组合框控件的自动完成窗口那样,调整右下角无边框窗口的大小。

我找不到配置窗体以此方式的属性。

也许有人能够帮助我解决这个问题。

这里可以找到图片:

图片描述


发布一些代码。您可以通过更改控件的宽度和高度来调整大小。 - Andrew Keith
由于Andrew Keith的评论,修改了问题并添加了屏幕截图链接:用户应该能够调整表单大小。 - Chris U
看看我的解决方案,使用面板:http://stackoverflow.com/a/8848440/640781 - edid
4个回答

35

这是对Franci解释的代码,我正在撰写它,但他同时回答了,如果此代码适合您的需求,请投票支持他的解释,因为它很好。

protected override void WndProc(ref Message m) {
    const int wmNcHitTest = 0x84;
    const int htBottomLeft = 16;
    const int htBottomRight = 17;
    if (m.Msg == wmNcHitTest) {
        int x = (int) (m.LParam.ToInt64() & 0xFFFF);
        int y = (int) ((m.LParam.ToInt64() & 0xFFFF0000) >> 16);
        Point pt = PointToClient(new Point(x, y));
        Size clientSize = ClientSize;
        if (pt.X >= clientSize.Width - 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16) {
            m.Result = (IntPtr) (IsMirrored ? htBottomLeft : htBottomRight);
            return;
        }
    }
    base.WndProc(ref m);
}

编辑:要编写手柄,您可以初始化一个new VisualStyleRenderer(VisualStyleElement.Status.Gripper.Normal)并使用其PaintBackground()方法。


1
在 https://dev59.com/ElTTa4cB1Zd3GeqPpBVh#4918111 提供了有关绘制夹爪的更多说明。 - JYelton

23

非常感谢您发布这个很棒的示例和说明。我在下面添加了一些其他人可能会感兴趣的内容。这里的一些代码来自其他stackoverflow帖子,但是将它们放在一个代码块中以便于他人查看可能会有所帮助。我希望能够在所有边框上调整表单大小,而不仅仅是右下角。我还想能够拖动表单。最后,我想要一个投影。

//***********************************************************
//This gives us the ability to resize the borderless from any borders instead of just the lower right corner
protected override void WndProc(ref Message m)
{
    const int wmNcHitTest = 0x84;
    const int htLeft = 10;
    const int htRight = 11;
    const int htTop = 12;
    const int htTopLeft = 13;
    const int htTopRight = 14;
    const int htBottom = 15;            
    const int htBottomLeft = 16;
    const int htBottomRight = 17;          

    if (m.Msg == wmNcHitTest)
    {
        int x = (int)(m.LParam.ToInt64() & 0xFFFF);
        int y = (int)((m.LParam.ToInt64() & 0xFFFF0000) >> 16);
        Point pt = PointToClient(new Point(x, y));
        Size clientSize = ClientSize;
        ///allow resize on the lower right corner
        if (pt.X >= clientSize.Width - 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16)
        {           
            m.Result = (IntPtr)(IsMirrored ? htBottomLeft : htBottomRight);
            return;
        }       
        ///allow resize on the lower left corner
        if (pt.X <= 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16)
        {
            m.Result = (IntPtr)(IsMirrored ? htBottomRight : htBottomLeft);
            return;
        }
        ///allow resize on the upper right corner
        if (pt.X <= 16 && pt.Y <= 16 && clientSize.Height >= 16)
        {
            m.Result = (IntPtr)(IsMirrored ? htTopRight : htTopLeft);
            return;
        }
        ///allow resize on the upper left corner
        if (pt.X >= clientSize.Width - 16 && pt.Y <= 16 && clientSize.Height >= 16)
        {
            m.Result = (IntPtr)(IsMirrored ? htTopLeft : htTopRight);
            return;
        }
        ///allow resize on the top border
        if (pt.Y <= 16 && clientSize.Height >= 16)
        {
            m.Result = (IntPtr)(htTop);
            return;
        }
        ///allow resize on the bottom border
        if (pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16)
        {
            m.Result = (IntPtr)(htBottom);
            return;
        }
        ///allow resize on the left border
        if (pt.X <= 16 && clientSize.Height >= 16)
        {
            m.Result = (IntPtr)(htLeft);
            return;
        }
        ///allow resize on the right border
        if (pt.X >= clientSize.Width - 16 && clientSize.Height >= 16)
        {
            m.Result = (IntPtr)(htRight);
            return;
        }
    }
    base.WndProc(ref m);
}
//***********************************************************
//***********************************************************
//This gives us the ability to drag the borderless form to a new location
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;

[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();

private void YOURCONTROL_MouseDown(object sender, MouseEventArgs e)
{
    //ctrl-leftclick anywhere on the control to drag the form to a new location 
    if (e.Button == MouseButtons.Left && Control.ModifierKeys == Keys.Control)
    {       
        ReleaseCapture();
        SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
    }  
}
//***********************************************************
//***********************************************************
//This gives us the drop shadow behind the borderless form
private const int CS_DROPSHADOW = 0x20000;
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ClassStyle |= CS_DROPSHADOW;
        return cp;
    }
}
//***********************************************************

15
实现这个的正确方法是添加一个消息处理程序(例如通过覆盖Form.WndProc),并处理WM_NCHITTEST消息。当您接收到消息时,特别是在计算命中测试是否针对您指定的调整大小区域时,如果是,请返回HTBOTTOMRIGHT。默认窗口过程将为您完成其余工作,因为它将假定用户已单击窗口边框的右下角,即使您的窗口没有边框也是如此。(您可以在PInvoke.net上找到该消息的C#定义)
这种方法需要一点Win32互操作,但它会使您的调整大小看起来与任何其他窗口调整大小完全相同。
简单的方法是像@benPearce说的那样,在角落里放置一个面板,并使用Width/Height调整表单大小。它会工作,但调整大小不会很平滑,尤其是在Vista和Win7 Basic上,标准移动和调整大小上禁用了完整重绘,而会尝试在每个步骤上重绘。
更新:在这两种方法中,您还必须想办法绘制gripper。例如,您可以放置标准gripper的位图。虽然,考虑到您的表单没有标题和边框,因此您不一定被困在标准Windows视觉效果中,您可能会选择更加时尚的东西。 更新2:如果您有一个控件覆盖整个窗口,它将会吞噬表单鼠标消息。您需要以某种方式剪切出要用于调整大小的位置。您有几个选项来处理这个问题:
  1. 调整控件大小以腾出空间用于调整大小。
  2. 通过区域属性(Region property)微调控件区域,以排除调整大小的手柄。
  3. 使用面板覆盖调整大小的手柄,监听其MouseEnter消息,并将表单Capture属性设置为true,这将导致所有后续鼠标消息都发送到它。 注意:一旦调整大小完成并且鼠标离开该区域,您必须释放捕获。

我建议选择选项1,因为它最简单。选项3是最复杂的,需要了解Windows中鼠标输入的详细信息,因此我不建议使用它。选项2是选项1的很好替代方案,但您需要尝试一下看看ListView控件对其区域进行微调的反应如何。


2
非常感谢,这对于空表单非常有效。但是我的表单包含一个填充表单的列表视图。没有触发 WM_NCHITTEST 消息。 - Chris U
1
任何想要了解如何绘制夹持器的人,可以从 ControlPaint.DrawSizeGrip 开始。 - AnotherUser

2

将面板或其他控件放在角落里,使用面板的MouseDown和MouseMove事件,适当调整表单大小。

在MouseDown中,记录坐标,在MouseMove中计算与原始位置的差异以调整表单大小。


1
我认为第二句话中的“MouseDown”最后一次出现应该是“MouseMove”。 - bentsai
1
这需要一些工作,但我喜欢干净的事件驱动解决方案,比其他建议更好。谢谢。 - BrianLegg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接