允许用户在运行时调整控件大小






4.85/5 (42投票s)
使用此类和两行代码在运行时启用窗体上控件的调整大小功能。
引言
在 Web 上搜索(包括此站点)了一些简单的代码,这些代码允许最终用户在运行时调整控件的大小之后,我最终得出结论,还没有任何真正有效但又非常简单的东西,我甚至可以将其用作基础。我非常愿意修改一些东西来完成我想要做的事情,但大多数实现要么有错误,要么过于复杂,要么就是很糟糕。我没有找到一个真正有效的实现。
最终,我决定自己编写一个。我做到了,它相对简单(大约花了 2 个小时编写),而且非常容易使用。
背景
基本上,我们在这里试图做的是创建一些东西,允许用户在运行时调整和移动控件,就像我们开发人员在设计时能够做的那样。此代码为您(开发人员)提供了一个相当坚实的基础,您可以从中创建任何您想要的自定义行为。与我发现的其他实现相比,这是我见过的最简单、最有效的一个。
Using the Code
它基本上由一个类组成,该类可以包含在项目中的任何位置,然后是几行代码来“挂钩”该类到您想要启用运行时调整大小的控件。
首先,让我们看看如何“挂钩”控件(换句话说,如何使用该类使任何控件在运行时可调整大小)
Public Class Form1
Dim rc As ResizeableControl
Private Sub Form1_Load(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles MyBase.Load
rc = New ResizeableControl(pbDemo)
End Sub
End Class
就是这样!够简单吧?
您需要将 rc
变量保留在窗体级别,这样它就不会超出范围。当窗体加载时,只需创建 ResizeableControl
的一个实例,将其传递给您想要调整大小的控件(在本例中为名为 pbDemo
的 picturebox
,但可以是任何控件),并将新实例分配给窗体级别的 rc
变量。如果希望多个控件可调整大小,您可以在窗体级别创建一个 ResizeableControl
对象的数组或集合。
现在让我们看看这个类本身
Public Class ResizeableControl
Private WithEvents mControl As Control
Private mMouseDown As Boolean = False
Private mEdge As EdgeEnum = EdgeEnum.None
Private mWidth As Integer = 4
Private mOutlineDrawn As Boolean = False
Private Enum EdgeEnum
None
Right
Left
Top
Bottom
TopLeft
End Enum
Public Sub New(ByVal Control As Control)
mControl = Control
End Sub
Private Sub mControl_MouseDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles mControl.MouseDown
If e.Button = Windows.Forms.MouseButtons.Left Then
mMouseDown = True
End If
End Sub
Private Sub mControl_MouseUp(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles mControl.MouseUp
mMouseDown = False
End Sub
Private Sub mControl_MouseMove(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles mControl.MouseMove
Dim c As Control = CType(sender, Control)
Dim g As Graphics = c.CreateGraphics
Select Case mEdge
Case EdgeEnum.TopLeft
g.FillRectangle(Brushes.Fuchsia, _
0, 0, mWidth * 4, mWidth * 4)
mOutlineDrawn = True
Case EdgeEnum.Left
g.FillRectangle(Brushes.Fuchsia, _
0, 0, mWidth, c.Height)
mOutlineDrawn = True
Case EdgeEnum.Right
g.FillRectangle(Brushes.Fuchsia, _
c.Width - mWidth, 0, c.Width, c.Height)
mOutlineDrawn = True
Case EdgeEnum.Top
g.FillRectangle(Brushes.Fuchsia, _
0, 0, c.Width, mWidth)
mOutlineDrawn = True
Case EdgeEnum.Bottom
g.FillRectangle(Brushes.Fuchsia, _
0, c.Height - mWidth, c.Width, mWidth)
mOutlineDrawn = True
Case EdgeEnum.None
If mOutlineDrawn Then
c.Refresh()
mOutlineDrawn = False
End If
End Select
If mMouseDown And mEdge <> EdgeEnum.None Then
c.SuspendLayout()
Select Case mEdge
Case EdgeEnum.TopLeft
c.SetBounds(c.Left + e.X, c.Top + e.Y, _
c.Width, c.Height)
Case EdgeEnum.Left
c.SetBounds(c.Left + e.X, c.Top, _
c.Width - e.X, c.Height)
Case EdgeEnum.Right
c.SetBounds(c.Left, c.Top, _
c.Width - (c.Width - e.X), c.Height)
Case EdgeEnum.Top
c.SetBounds(c.Left, c.Top + e.Y, _
c.Width, c.Height - e.Y)
Case EdgeEnum.Bottom
c.SetBounds(c.Left, c.Top, _
c.Width, c.Height - (c.Height - e.Y))
End Select
c.ResumeLayout()
Else
Select Case True
Case e.X <= (mWidth * 4) And _
e.Y <= (mWidth * 4) 'top left corner
c.Cursor = Cursors.SizeAll
mEdge = EdgeEnum.TopLeft
Case e.X <= mWidth 'left edge
c.Cursor = Cursors.VSplit
mEdge = EdgeEnum.Left
Case e.X > c.Width - (mWidth + 1) 'right edge
c.Cursor = Cursors.VSplit
mEdge = EdgeEnum.Right
Case e.Y <= mWidth 'top edge
c.Cursor = Cursors.HSplit
mEdge = EdgeEnum.Top
Case e.Y > c.Height - (mWidth + 1) 'bottom edge
c.Cursor = Cursors.HSplit
mEdge = EdgeEnum.Bottom
Case Else 'no edge
c.Cursor = Cursors.Default
mEdge = EdgeEnum.None
End Select
End If
End Sub
Private Sub mControl_MouseLeave(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles mControl.MouseLeave
Dim c As Control = CType(sender, Control)
mEdge = EdgeEnum.None
c.Refresh()
End Sub
End Class
仅此而已。您可以下载示例并试用,或者直接从本文中剪切并粘贴代码。
关注点
如您所见,代码不多,但足以使其工作。我建议您将其用作起点,然后对其进行自定义以满足您的需求。
例如,品红色边框可以替换为大小调整手柄和控件周围的虚线(类似于 .NET 窗体设计器)。您还可以添加能够抓取一个角并同时垂直和水平拉伸控件的能力(再次类似于 .NET 窗体设计器)。
实际上,您可以做的事情没有限制,但至少这为您提供了一个起点,而且它“开箱即用”的效果非常好。
尽情享用!
历史
- 2007 年 10 月 2 日:初始帖子