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

时间:2009-10-08 05:49:05

标签: c# winforms

我希望用户在右下角调整无边框窗口的大小,就像我可以调整组合框控件的自动完成窗口一样。

我无法找到以这种方式配置表单的属性。

也许有人可以帮我解决这个问题。

可在此处找到图片:

enter image description here

4 个答案:

答案 0 :(得分:32)

这是与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 :(得分:19)

非常感谢您发布这个精彩的样本和解释。我添加了一些其他人可能感兴趣的附加内容。这里的一些代码来自其他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;
    }
}
//***********************************************************

答案 2 :(得分:13)

实现此目的的正确方法是在表单中添加消息proc处理程序(例如通过覆盖Form.WndProc)并处理WM_NCHITTEST消息。 (您可以在PInvoke.net上找到该消息的C#定义)特别是,当您收到消息时,计算命中测试是否针对您指定用于调整大小的区域中的某个点,如果是,则返回HTBOTTOMRIGHT。默认窗口proc将为您完成剩下的工作,因为它会假设用户已经点击了窗口边框的右下角,即使您的窗口没有边框。

这个方法需要一小部分Win32互操作,但它会使你的调整大小看起来像任何其他窗口调整大小。

简单的方法是按照@benPearce的说法进行操作,并在角落放置一个面板,并使用Width / Height调整表单大小。它会起作用,但调整大小并不顺利,尤其是在Vista和Win7 Basic上,在标准移动和调整大小时禁用完全重绘,同时尝试重绘每一步。

更新:在这两种方法中,您还必须弄清楚如何绘制抓手。例如,您可以放置​​标准夹具的位图。虽然,鉴于您的表单没有标题和边框,因此您不一定会遇到标准的Windows视觉效果,您可能会选择使用更加时髦的东西。

更新2 :如果您有一个覆盖整个窗口的控件,它将使用表单鼠标消息。你必须以某种方式剪切你想要用来调整控件的大小。您有几种方法可以解决这个问题:

  1. 调整控件的大小,为调整大小的手柄留出一些空间。
  2. 调整控件区域(通过Region属性)以排除调整大小的手柄。
  3. 覆盖面板的大小调整手柄,监听其MouseEnter消息并将表单Capture属性设置为true,这将导致所有进一步的鼠标消息转到它。 注意:在调整大小完成后鼠标离开该区域时,您必须释放捕获。
  4. 我建议选择最简单的选项1。选项3是最复杂的,需要有关鼠标输入如何在Windows中工作的详细信息,所以我不推荐它。选项2是选项1的一个很好的替代方案,但你必须尝试看看ListView控件如何对其被调整的区域做出反应。

答案 3 :(得分:2)

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

在MouseDown中,我会记录坐标,然后在MouseMove中,您可以计算与原始位置的差异,以调整表格大小。