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

旋转 PictureBox 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.39/5 (14投票s)

2005年4月26日

CPOL

4分钟阅读

viewsIcon

183830

downloadIcon

5277

一个 PictureBox 控件,允许您旋转图像。

Sample Image - rimage.jpg

引言

您有多少次想在 PictureBox 控件中旋转图像?我知道我曾多次想这样做。

此控件使旋转图像变得简单。在代码中引用它很容易 - 命名空间是 System.Windows.Forms,因此您可以轻松地将其声明为 RImage

属性/方法

此控件继承了所有内容,因此 PictureBox 拥有的任何属性/方法,此控件都将拥有 - 但是,有几个属性将为您提供内置于控件中的其他选项。

  • 公共属性 ShowThrough() As Boolean
  • 公共属性 Direction() As DirectionEnum
  • 公共属性 Rotation() As Integer
  • 公共属性 TransparentColor() As Color

ShowThrough 将决定图像未使用的空间是否透明并显示其下方的控件。这是通过区域实现的。

Direction 如您所见,它被声明为 DirectionEnum。这个枚举是为该控件创建的。它告诉控件旋转图像的方向:Clockwise(顺时针)或 Counter_Clockwise(逆时针)。

Rotation 是图像的旋转角度。单位是度。范围是 0 到 359;但是,输入超出范围的数字会将其缩放到范围内的相应角度。

TransparentColor 允许您为图像设置透明颜色。演示项目包含一个带有青绿色背景的图像。如果将 TransparentColor 属性设置为青绿色,则图像中的该颜色将变为透明。不幸的是,它不会透过显示下方的控件,只会显示父级的背景颜色。

添加控件

右键单击工具箱的空白区域,然后选择“添加/删除项”。在对话框屏幕的“.NET Framework 组件”选项卡上,选择“浏览”并导航到 DLL 文件。完成此操作后,单击“确定”。

您现在已将控件添加到工具箱。

使用控件

使用该控件很简单。它的工作方式几乎与 PictureBox 控件完全相同。将一个添加到您的窗体,并为其指定一张图片。一旦有了图片,ShowThrough 就会开始工作(如果没有图片,OnPaint 会在设置透明区域之前退出)如果它被设置了。

现在,只需在“属性”窗口的下拉框中设置您的 Direction,然后输入 Rotation 的角度。

如果您想为图像设置透明颜色 - 您可以使用“属性”窗口中的 TransparentColor 来实现。

工作原理

所有旋转都在 OnPaint 事件中处理。我首先获取图像的当前角点。

Dim bm_in As New Bitmap(MyBase.Image)

Dim wid As Single = bm_in.Width
Dim hgt As Single = bm_in.Height

Dim corners As Point() = { _
    New Point(0, 0), _
    New Point(wid, 0), _
    New Point(0, hgt), _
    New Point(wid, hgt)}

接下来,我获取图像的中心 - 我们要围绕其旋转的点 - 并从中减去每个角点。

Dim cx As Single = wid / 2
Dim cy As Single = hgt / 2
Dim i As Long

For i = 0 To 3
    corners(i).X -= cx
    corners(i).Y -= cy
Next

现在我们需要获取 theta 的正弦和 theta 的余弦 - 这意味着我们需要 theta。

Dim theta As Single = CSng((_degree) * _direction) * PI / 180
Dim sin_theta As Single = Sin(theta)
Dim cos_theta As Single = Cos(theta)

这里是关键所在,我们需要将旋转公式应用于所有角点。

Dim X As Single
Dim Y As Single

For i = 0 To 3
    X = corners(i).X
    Y = corners(i).Y
    corners(i).X = (X * cos_theta) - (Y * sin_theta)
    corners(i).Y = (Y * cos_theta) + (X * sin_theta)
Next

好了,我们得到了旋转后的角点,让我们来修复找到旋转点时产生的偏移量,为此我们需要最小的 x 和 y 值。

Dim xmin As Single = corners(0).X
Dim ymin As Single = corners(0).Y

For i = 1 To 3
    If xmin > corners(i).X Then xmin = corners(i).X
    If ymin > corners(i).Y Then ymin = corners(i).Y
Next

For i = 0 To 3
    corners(i).X -= xmin
    corners(i).Y -= ymin
Next

现在我们可以实际输出旋转后的图像了,但首先我使用一个函数创建一个基于这些角点的区域。

Dim bm_out As New Bitmap(CInt(-2 * xmin), CInt(-2 * ymin))
Dim bgr As Graphics = Graphics.FromImage(bm_out)
Dim rg As Region = CreateTransRegion(corners)
Dim tp As Point = corners(3)
ReDim Preserve corners(2)
bgr.DrawImage(bm_in, corners)

现在我们在输出缓冲区中得到了旋转后的图像,以及一个区域,允许对不会绘制图像的控件部分进行透明处理。现在来实现 SizeMode。对于 StretchImage,我们需要旋转图像的宽度和高度 - 这很容易,因为它存储在 corners 数组的索引 3 处 - 对于拉伸或居中,我们需要一个新的区域。

Dim gr_out As Graphics = pe.Graphics
gr_out.FillRectangle(New SolidBrush(Me.BackColor), 0, 0, Me.Width, Me.Height)
bm_in.MakeTransparent(_transColor)
If _sizemode = PictureBoxSizeMode.StretchImage Then
    Dim maxW As Integer = tp.X
    Dim maxH As Integer = tp.Y
    For t As Integer = 0 To 2
        If maxW < corners(t).X Then maxW = corners(t).X
        If maxH < corners(t).Y Then maxH = corners(t).Y
    Next
    'get hscale
    Dim hscale As Double = Me.Width / maxW
    'get vscale
    Dim vscale As Double = Me.Height / maxH
    'convert points
    corners(0) = New Point(corners(0).X * hscale, corners(0).Y * vscale)
    corners(1) = New Point(corners(1).X * hscale, corners(1).Y * vscale)
    corners(2) = New Point(corners(2).X * hscale, corners(2).Y * vscale)
    gr_out.DrawImage(bm_out, 0, 0, Me.Width, Me.Height)
    Dim np(3) As Point
    np(0) = corners(0)
    np(1) = corners(1)
    np(2) = corners(2)
    np(3) = New Point(tp.X * hscale, tp.Y * vscale)
    rg = CreateTransRegion(np)

对于居中图像,我们不需要那么多。

ElseIf _sizemode = PictureBoxSizeMode.CenterImage Then
    Dim wadd As Integer = CInt((Me.Width / 2) - (bm_out.Width / 2))
    Dim hadd As Integer = CInt((Me.Height / 2) - (bm_out.Height / 2))
    corners(0) = New Point(corners(0).X + wadd, corners(0).Y + hadd)
    corners(1) = New Point(corners(1).X + wadd, corners(1).Y + hadd)
    corners(2) = New Point(corners(2).X + wadd, corners(2).Y + hadd)
    gr_out.DrawImage(bm_in, corners)
    Dim np(3) As Point
    np(0) = corners(0)
    np(1) = corners(1)
    np(2) = corners(2)
    np(3) = New Point(tp.X + wadd, tp.Y + hadd)
    rg = CreateTransRegion(np)

任何其他大小模式都会输出到 0,0,所以我们不需要特别处理,除了 AutoSize - 它只是将控件的大小更改为与图像匹配。

Else
    gr_out.DrawImage(bm_in, corners)
End If
If _sizemode = PictureBoxSizeMode.AutoSize Then
    MyBase.Width = bm_out.Width
    MyBase.Height = bm_out.Height
End If

我们处理的最后一件事是区域(用于透明度),但如果属性 ShowThrough 被更改为 False,那么我们需要确保删除任何现有区域。

Me.Region = Nothing
If _showThrough Then
    Me.Region = rg
End If

就是这样!当然可以修改它以围绕中心以外的点进行旋转(尽管我还没有尝试过)。

© . All rights reserved.