I need to draw a different progress bar through VisualStyleRenderer
. Everything works fine if I use Graphics
of OnPaint
method. But since I want to save it in hard drive, I need to render progressbar in Bitmap
object and then save it.
Here is example code
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawImage(RenderProgressbarImage(), new Point(5, 5));
//following code works good
progressRenderer.SetParameters("PROGRESS", 11, 2);
progressRenderer.DrawBackground(e.Graphics, new Rectangle(125, 5, 100, 13));
}
VisualStyleRenderer progressRenderer = new VisualStyleRenderer(VisualStyleElement.ProgressBar.Bar.Normal);
Bitmap RenderProgressbarImage()
{
Bitmap bmp = new Bitmap(100, 13);
using (Graphics g = Graphics.FromImage((Image)bmp))
{
progressRenderer.SetParameters("PROGRESS", 11, 2);
progressRenderer.DrawBackground(g, new Rectangle(0, 0, bmp.Width, bmp.Height));
}
return bmp;
}
But if I draw it in Bitmap, it have black corners instead of transparent. However if it uses Graphics
of OnPaint
, everything draws good.
Using Bitmap
, you will a rectangular object using GDI+ the way you are doing it.
Creating an Image with Rounded Corners might help you with creating a rounded bitmap image as you'd like.
Edit - Modified RenderProgressbarImage
to take a Graphics
object as an input
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawImage(RenderProgressbarImage(e.Graphics), new Point(5, 5));
//Test to Check for Output
RenderProgressbarImage(e.Graphics).Save(@"C:\Bitmap.bmp");;
//following code works good
progressRenderer.SetParameters("PROGRESS", 11, 2);
progressRenderer.DrawBackground(e.Graphics, new Rectangle(125, 5, 100, 13));
}
Bitmap RenderProgressbarImage(Graphics g)
{
Bitmap bmp = new Bitmap(100, 13, g);
progressRenderer.SetParameters("PROGRESS", 11, 2);
progressRenderer.DrawBackground(g, new Rectangle(0, 0, bmp.Width, bmp.Height));
return bmp;
}
Edit2: Modified to simplify solution per OP's comment below
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Bitmap bmp = new Bitmap(100, 13, e.Graphics);
bmp.Save(<SomefilePath.png>);
//following code works good
progressRenderer.SetParameters("PROGRESS", 11, 2);
progressRenderer.DrawBackground(e.Graphics, new Rectangle(125, 5, 100, 13));
}
A note on this: doing a save of the Bitmap
in the OnPaint
event will be a definite performance hit on rendering. Perhaps just update a Bitmap
variable in your class and save the Bitmap
periodically from a different Thread
/ some Timer
/etc.; it all depends on your needs.
I know it's old but I faced the same problem and after a lot of research I found a solution, I hope it's help someone.
// Created by: Motaz Alnuweiri
// Reference:
// URL1: https://www.autoitscript.com/forum/topic/181956-drawthemebackground-bitmap-alpha/
// URL2: https://gist.github.com/wavescholar/11297223#file-gdi-bitmap-conversion-L71
// URL3: https://www.experts-exchange.com/questions/20872978/BITMAPINFOHEADER-from-NET-Bitmap.html
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
public class Helper
{
#region Win32 Native APIs
internal class NativeMethods
{
// CreateDIBSection funcation iUsage value
internal const int DIB_RGB_COLORS = 0x00;
internal const int DIB_PAL_COLORS = 0x01;
internal const int DIB_PAL_INDICES = 0x02;
[DllImport("gdi32.dll", CharSet = CharSet.Unicode)]
internal static extern bool DeleteObject(IntPtr hObject);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern int InvalidateRect(IntPtr hwnd, IntPtr rect, int bErase);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32.dll", CharSet = CharSet.Unicode)]
internal static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("gdi32.dll", CharSet = CharSet.Unicode)]
internal static extern int DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll", CharSet = CharSet.Unicode)]
internal static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32.dll", CharSet = CharSet.Unicode)]
internal static extern IntPtr CreateDIBSection(IntPtr hdc, ref BITMAPINFO bmi, uint iUsage,
out IntPtr bits, IntPtr hSection, uint dwOffset);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
internal static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);
[StructLayout(LayoutKind.Sequential)]
internal struct BITMAPINFO
{
public Int32 biSize;
public Int32 biWidth;
public Int32 biHeight;
public Int16 biPlanes;
public Int16 biBitCount;
public Int32 biCompression;
public Int32 biSizeImage;
public Int32 biXPelsPerMeter;
public Int32 biYPelsPerMeter;
public Int32 biClrUsed;
public Int32 biClrImportant;
}
}
#endregion
public static Image VisualStyleRendererToImage(VisualStyleElement element, Rectangle bounds)
{
if (ToolStripManager.VisualStylesEnabled && VisualStyleRenderer.IsElementDefined(element))
{
VisualStyleRenderer renderer = new VisualStyleRenderer(element);
using (Bitmap bit = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb))
{
NativeMethods.BITMAPINFO bmi = new NativeMethods.BITMAPINFO();
bmi.biWidth = bit.Width;
bmi.biHeight = bit.Height;
bmi.biPlanes = 1;
bmi.biBitCount = 32;
bmi.biXPelsPerMeter = (int)bit.HorizontalResolution;
bmi.biYPelsPerMeter = (int)bit.VerticalResolution;
bmi.biSize = Marshal.SizeOf(typeof(NativeMethods.BITMAPINFO));
IntPtr bits;
IntPtr bmp = NativeMethods.CreateDIBSection(IntPtr.Zero, ref bmi,
NativeMethods.DIB_RGB_COLORS, out bits, IntPtr.Zero, 0);
IntPtr dc = NativeMethods.GetDC(IntPtr.Zero);
IntPtr hdc = NativeMethods.CreateCompatibleDC(dc);
NativeMethods.SelectObject(hdc, bmp);
using (Graphics g = Graphics.FromHdc(hdc))
{
renderer.DrawBackground(g, bounds);
}
Bitmap image = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppPArgb);
using (Bitmap tempImage = new Bitmap(bounds.Width, bounds.Height, bounds.Width * 4,
PixelFormat.Format32bppPArgb, bits))
{
BitmapData tempBitmapData = tempImage.LockBits(bounds, ImageLockMode.ReadOnly,
PixelFormat.Format32bppPArgb);
BitmapData bitmapData = image.LockBits(bounds, ImageLockMode.WriteOnly,
PixelFormat.Format32bppPArgb);
NativeMethods.CopyMemory(bitmapData.Scan0, tempBitmapData.Scan0,
(uint)tempBitmapData.Stride * (uint)tempBitmapData.Height);
tempImage.UnlockBits(tempBitmapData);
image.UnlockBits(bitmapData);
}
NativeMethods.DeleteObject(bmp);
NativeMethods.DeleteDC(hdc);
NativeMethods.ReleaseDC(IntPtr.Zero, dc);
return image;
}
}
else
{
return new Bitmap(bounds.Width, bounds.Height);
}
}
}
Reference:
URL1: https://www.autoitscript.com/forum/topic/181956-drawthemebackground-bitmap-alpha/
URL2: https://gist.github.com/wavescholar/11297223#file-gdi-bitmap-conversion-L71
URL3: https://www.experts-exchange.com/questions/20872978/BITMAPINFOHEADER-from-NET-Bitmap.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With