Drawing reflection of progress control in winforms VB

Here is an image of what I'm trying to achieve:

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

As you can see, there is a slight reflection on the progress bar.

I have a custom progress bar that is pretty much based on this code:
http://www.codeproject.com/Articles/19309/Vista-Style-Progress-Bar-in-C

Note. My code is in VB.

Problem . I would like to draw a reflection of this progress bar so that it looks the same as the image above. I was told that one way to do this is to use pixels, which must be done manually. Is this the only option? Is there any other / easier way to do this?

I appreciate your help. Thanks!

+4
source share
2 answers

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 to get a shade of gray, 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 the options to make the shadow more realistic.

The solution is based on this article:

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

+8
source

This solution serves more code, but many times faster than GetPixel / SetPixel. It has one overload without any additional settings, or you can use it with alpha start and stop value, as well as how much you want to β€œcompress” the reflection.

The overloaded simple version assumes that the background color will be the same as the parent. Please note that there is no error checking. Of course, you need to implement this in production code.

The result will be like this: (many thanks to Neolisk for surviving the additional problem of creating an image from the code)

enter image description here

There is still room for optimization (it works only with the "compressed" version, without boxing, etc.), but I will leave this as a performance for the user :-)

 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 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 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 
+2
source

Source: https://habr.com/ru/post/1445261/


All Articles