2009-10-08 194 views
14

我想让用户调整右下角的无边框窗口的大小,就像我可以调整组合框控件的自动填充窗口一样。调整右下角的无边界窗口

我无法找到属性来配置表单。

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

的图像可以在这里找到:

enter image description here

+0

发表了一些代码。您可以通过更改控件的宽度和高度来调整大小。 – 2009-10-08 05:50:52

+0

由于Andrew Keith的评论,修改了问题并添加了截图的链接:用户应该能够调整表单的大小。 – 2009-10-08 05:59:21

+0

使用面板查看我的解决方案:http://stackoverflow.com/a/8848440/640781 – edid 2012-01-13 09:42:07

回答

13

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

这个问题需要一点点的Win32 interop,但它会使你的调整大小看起来像其他任何窗口调整大小。

最简单的方法是按@benPearce的说法,在面板的角落放置一个面板,并使用宽度/高度调整窗体大小。它会起作用,但调整大小不会一帆风顺,特别是在Vista和Win7 Basic中,在标准移动和重新调整大小时完全重绘被禁用,而每一步都将尝试重绘。

更新:在这两种方法中,您将不得不弄清楚如何绘制抓手。例如,您可以放置​​标准抓手的位图。尽管如此,由于您的表单没有标题和边框,因此您不一定会使用标准的Windows视觉效果,您可能会选择更快捷的方式。

更新2:如果您有一个覆盖整个窗口的控件,它将吃掉表单鼠标消息。你必须以某种方式剪辑你想用来调整大小的地方。您有几种选择来处理这个:

  1. 调整控制,使尺寸调整握一些空间。
  2. 调整控制区域(通过Region属性)以排除调整大小的控制点。
  3. 覆盖调整大小控制面板,听取它的MouseEnter消息,并将Capture属性设置为true,这将导致所有更多的鼠标消息到达它。 注意:调整大小完成后,鼠标离开该区域后,您将不得不释放捕获。

我会推荐去选择最简单的选项1。选项3是最复杂的,需要关于鼠标输入在Windows中的工作方式的详细信息,所以我不会推荐它。选项2是选项1的一个很好的选择,但您必须尝试查看ListView控件如何对其区域进行调整。

+1

非常感谢,这对于静态表单非常有用。但是我的表单包含一个填充表单的列表视图。没有WM_NCHITTEST消息被激发。 – 2009-10-08 06:41:38

+1

任何人都在寻找如何绘制抓手,'ControlPaint.DrawSizeGrip'是一个开始。 – AnotherUser 2014-07-02 11:23:38

2

将面板或在角落里其他一些控制,使用面板的MouseDown和mousemove事件时,调整形式大小适当。

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

+0

我认为第二句中“MouseDown”的最后一个实例应该是“MouseMove”。 – bentsai 2010-02-17 14:32:50

+0

正确!更新。 – benPearce 2010-02-17 22:01:50

+0

这花了一些工作,但我更喜欢干净的事件驱动的解决方案比其他建议更好。谢谢 – BrianLegg 2015-12-24 19:49:30

31

下面是与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

有关绘制抓手的更多说明,请参阅http://stackoverflow.com/a/4918111/161052 – JYelton 2012-11-28 20:54:55

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; 
    } 
} 
//***********************************************************