5

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.

screenshot

xmen
  • 1,947
  • 2
  • 25
  • 47

2 Answers2

1

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.

Community
  • 1
  • 1
jordanhill123
  • 4,142
  • 2
  • 31
  • 40
  • Creating image with rounded corner is different thing. That's not exactly what I want. I need to draw more using VisualStyleRenderer. – xmen Apr 16 '13 at 07:29
  • Let me see if I can get a working example for you. I'm more so pointing you towards the `Graphics` routine used in that case for handling the corners. `e.Graphics` already has this working in the `OnPaint` event – jordanhill123 Apr 16 '13 at 07:33
  • Sorry, I don't understand what are you trying to say. – xmen Apr 16 '13 at 07:51
  • The `Graphics` object was the cause for non-rounded corners; using the rounded corners `Graphics` routine from that question was one option but passing the `Graphics` from `OnPaint` is the simplest solution – jordanhill123 Apr 16 '13 at 08:07
  • yes but I do not need to draw on control, I need it to save as png. It's only possible if I draw it using 'OnPaint' and then call 'DrawToBitmap' of that control but thats bad idea, really bad. – xmen Apr 16 '13 at 08:11
  • So you don't need any custom drawing; just a save of the control as a png image? – jordanhill123 Apr 16 '13 at 08:16
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/28309/discussion-between-xmen-w-k-and-jordanhill123) – xmen Apr 16 '13 at 12:30
  • @xmenW.K. and jordanhill123: Were you able to accomplish saving to an image? – Sabuncu Mar 21 '14 at 21:22
  • Saving image was not a problem, rounded corner was. No, no solution was found by now. – xmen Mar 22 '14 at 01:41
  • @xmenW.K. Please see this answer: http://stackoverflow.com/a/22571022/360840 from LarsTech - it worked for me, I am able to save a VisualStyleElement to a file. The resolution will be the resolution you choose for the bitmap from which you derive the Graphics object. Let me know if you have questions. – Sabuncu Apr 02 '14 at 10:26
1

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

Motaz Alnuweiri
  • 145
  • 2
  • 7