4

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

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 中。

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

我感谢您的帮助。谢谢!

4

2 回答 2

8

Are you looking for something like this?

enter image description here

Here is the code:

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))

If you want greyscale shadow, replace this line

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

with these two:

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

You will get something like this:

enter image description here

You can play with parameters to make the shadow more realistic.

Solution is based on this article:

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

于 2012-11-10T23:28:25.127 回答
2

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

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

结果将是这样的:(非常感谢 Neolisk 经历了从代码生成图像的额外麻烦)

在此处输入图像描述

仍有优化空间(仅使用“压缩”版本,取消装箱计算等),但我将把它留给用户执行 :-)

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
于 2012-11-11T08:29:06.063 回答