65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (42投票s)

2007年10月2日

CPOL

3分钟阅读

viewsIcon

182674

downloadIcon

8329

使用此类和两行代码在运行时启用窗体上控件的调整大小功能。

引言

在 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 的一个实例,将其传递给您想要调整大小的控件(在本例中为名为 pbDemopicturebox,但可以是任何控件),并将新实例分配给窗体级别的 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 日:初始帖子
© . All rights reserved.