在winforms VB中绘制进度条控件的反射

时间:2012-11-10 21:48:26

标签: vb.net winforms graphics progress-bar

这是我想要实现的目标的图像:

http://www.findmysoft.com/img/news/Windows-7-Beta-1-with-Updated-Boot-Screen-Drops-Next-Month.jpg

正如您所看到的,进度条下有一点反映。

我有一个很大程度上基于此代码的自定义进度条:
http://www.codeproject.com/Articles/19309/Vista-Style-Progress-Bar-in-C

注意:我的代码是VB。

问题 - 我想在其下面绘制一个进度条的反映,因此它看起来与我上面给出的图像类似。我被告知,一种方法是使用像素,这需要手动完成。这是唯一的选择吗?还有其他/更简单的方法吗?

感谢您的帮助。 谢谢!

2 个答案:

答案 0 :(得分:8)

你在找这样的东西吗?

enter image description here

以下是代码:

Dim pgBarReflection As New Bitmap(ProgressBar1.Width, 20)
ProgressBar1.DrawToBitmap(pgBarReflection, ProgressBar1.ClientRectangle)

For x As Integer = 0 To pgBarReflection.Width - 1
  For y As Integer = 0 To pgBarReflection.Height - 1
    Dim alpha = 255 - 255 * y \ pgBarReflection.Height
    Dim clr As Color = pgBarReflection.GetPixel(x, y)
    clr = Color.FromArgb(alpha, clr.R, clr.G, clr.B)
    pgBarReflection.SetPixel(x, y, clr)
  Next y
Next x

Me.CreateGraphics.DrawImage(pgBarReflection, New Point(ProgressBar1.Left, ProgressBar1.Bottom + 10))

如果您想要灰度阴影,请替换此行

clr = Color.FromArgb(alpha, clr.R, clr.G, clr.B)

这两个:

Dim greyScale As Integer = CInt(clr.R * 0.3 + clr.G * 0.59 + clr.B * 0.11)
clr = Color.FromArgb(alpha, greyScale, greyScale, greyScale)

你会得到这样的东西:

enter image description here

您可以使用参数来使阴影更逼真。

解决方案基于这篇文章:

Draw an image with gradient alpha (opacity) values in VB.NET

答案 1 :(得分:2)

此解决方案可提供更多代码,但速度比GetPixel / SetPixel快许多倍。它有一个重载没有任何进一步的设置,或者你可以使用它与alpha开始和停止值以及你想要“挤压”反射的程度。

重载的简单版本假设背景颜色是父颜色。请注意,它没有错误检查。您当然需要在生产代码中实现它。

结果将是这样的:(非常感谢Neolisk在处理代码时产生图像的额外麻烦)

enter image description here

仍有优化空间(仅使用“挤压”版本,非拳击计算等),但我会将其留作用户的执行: - )

Private Sub DrawControlReflection(c As Control)
    DrawControlReflection(c, c.Parent.BackColor, 1, 0, 1, 7)  'set you defaults here
End Sub
''' <summary>
''' Draws an reflection of a control
''' </summary>
''' <param name="c">The control to make an reflection of</param>
''' <param name="bgCol">Background color in transparent area</param>
''' <param name="startTrans">0.0-1.0, start value of reflection transparency, usually 1</param>
''' <param name="endTrans">0.0-1.0, end value of reflection transparency, usually 0</param>
''' <param name="squeeze">height of reflection, values 0-1, 1=100%, 0.5=50% etc.</param>
''' <param name="delta">y offset of reflection from control's bottom</param>
''' <remarks>
''' Provided AS-IS.
''' Created by Epistmex, use as you want.
''' Need implementation of error checking (bitmap allocations etc.)
''' </remarks>
Private Sub DrawControlReflection(c As Control,
                                  bgCol As Color,
                                  startTrans As Single,
                                  endTrans As Single,
                                  squeeze As Single,
                                  delta As Integer)
    '
    '-- Original control's bound
    '
    Dim r As Rectangle = c.ClientRectangle
    '
    '-- Destination bound
    '
    Dim rd As Rectangle = New Rectangle(c.Left,
                                        c.Top + r.Height + 1 + delta,
                                        r.Width,
                                        CInt(r.Height * squeeze))
    '
    '-- Create a bitmap for reflection and copy control content into it
    '
    Dim bmp As New Bitmap(r.Width,
                          r.Height,
                          Imaging.PixelFormat.Format24bppRgb)

    c.DrawToBitmap(bmp, r)
    '
    '-- flip it vertically
    '
    bmp.RotateFlip(RotateFlipType.RotateNoneFlipY)
    '
    '-- Add gradient "transparency" to bitmap
    '
    AddGradientAlpha(bmp, r, startTrans, endTrans, bgCol)
    '
    '-- Draw the result
    '
    Dim g As Graphics = c.Parent.CreateGraphics
    if squeeze <> 1 Then g.InterpolationMode = _
                         Drawing2D.InterpolationMode.HighQualityBicubic

    g.DrawImage(bmp, rd)

    g.Dispose()

    bmp.Dispose()

End Sub
Private Sub AddGradientAlpha(ByRef bmp As Bitmap, r As Rectangle, s As Single, e As Single, bc As Color)

    Dim bmpLock As Imaging.BitmapData = bmp.LockBits(r, Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format24bppRgb)

    Dim st As Integer = bmpLock.Stride

    Dim bytesBmp(bmpLock.Stride * bmp.Height) As Byte

    Runtime.InteropServices.Marshal.Copy(bmpLock.Scan0, bytesBmp, 0, bytesBmp.Length)
    '
    '-- Calculate and create pre-multiplied gradient alpha
    '
    Dim x, y, dx, l, d As Integer
    Dim aDiff As Double = s - e
    Dim a As Double
    Dim b As Byte

    Dim h As Integer = bmp.Height - 1

    For y = 0 To h

        l = y * st 'line. cache the calculations we can
        d = h - y 'position with opposite value

        If d = 0 Then
            a = e
        Else
            a = (aDiff * d / h) + e 'gradient value ad 0.5 to h for even more accuracy
        End If

        If a < 0 Then a = 0
        If a > 1 Then a = 1

        a = a * a 'power of 2 to make gradient steeper

        For x = 0 To bmp.Width - 1

            dx = l + x * 3 'x pos in buffer

            'make gradient of colors in buffer + mix bg color
            bytesBmp(dx) = CByte(bytesBmp(dx) * a + ((1 - a) * bc.B))
            bytesBmp(dx + 1) = CByte(bytesBmp(dx + 1) * a + ((1 - a) * bc.G))
            bytesBmp(dx + 2) = CByte(bytesBmp(dx + 2) * a + ((1 - a) * bc.R))

        Next
    Next
    '
    '-- Marshal back
    '
    Runtime.InteropServices.Marshal.Copy(bytesBmp, 0, bmpLock.Scan0, bytesBmp.Length)
    bmp.UnlockBits(bmpLock)

End Sub