main
  1using System.Drawing;
  2using System.Drawing.Drawing2D;
  3using System.Windows.Forms;
  4
  5namespace MoMoney.Presentation.Winforms.Helpers
  6{
  7    public static class BitmapRegion
  8    {
  9        /// <summary>
 10        /// create and apply the region on the supplied control
 11        /// </summary>
 12        /// <param name="control">The Control object to apply the region to</param>
 13        /// <param name="bitmap">The Bitmap object to create the region from</param>
 14        public static void CreateControlRegion(Control control, Bitmap bitmap)
 15        {
 16            // Return if control and bitmap are null
 17            if (control == null || bitmap == null)
 18                return;
 19
 20            // Set our control's size to be the same as the bitmap + 6 pixels so that the borders don't affect it.
 21            control.Width = bitmap.Width;
 22            control.Height = bitmap.Height;
 23
 24            // Check if we are dealing with Form here
 25            if (control is Form)
 26            {
 27                // Cast to a Form object
 28                var form = (Form) control;
 29
 30                // Set our form's size to be a little larger that the bitmap just 
 31                // in case the form's border style is not set to none in the first place
 32                form.Width += 15;
 33                form.Height += 35;
 34
 35                // No border
 36                form.FormBorderStyle = FormBorderStyle.None;
 37
 38                // Set bitmap as the background image
 39                form.BackgroundImage = bitmap;
 40
 41                // Calculate the graphics path based on the bitmap supplied
 42                var graphicsPath = CalculateControlGraphicsPath(bitmap);
 43
 44                // Apply new region
 45                form.Region = new Region(graphicsPath);
 46            }
 47
 48                // Check if we are dealing with Button here
 49            else if (control is Button)
 50            {
 51                // Cast to a button object
 52                var button = (Button) control;
 53
 54                // Do not show button text
 55                button.Text = "";
 56
 57                // Change cursor to hand when over button
 58                button.Cursor = Cursors.Hand;
 59
 60                // Set background image of button
 61                button.BackgroundImage = bitmap;
 62
 63                // Calculate the graphics path based on the bitmap supplied
 64                var graphicsPath = CalculateControlGraphicsPath(bitmap);
 65
 66                // Apply new region
 67                button.Region = new Region(graphicsPath);
 68            }
 69        }
 70
 71        /// <summary>
 72        /// Calculate the graphics path that representing the figure in the bitmap 
 73        /// excluding the transparent color which is the top left pixel.
 74        /// </summary>
 75        /// <param name="bitmap">The Bitmap object to calculate our graphics path from</param>
 76        /// <returns>Calculated graphics path</returns>
 77        static GraphicsPath CalculateControlGraphicsPath(Bitmap bitmap)
 78        {
 79            // create GraphicsPath for our bitmap calculation
 80            var graphicsPath = new GraphicsPath();
 81
 82            // Use the top left pixel as our transparent color
 83            var colorTransparent = bitmap.GetPixel(0, 0);
 84
 85            // This is to store the column value where an opaque pixel is first found.
 86            // This value will determine where we start scanning for trailing opaque pixels.
 87            var colOpaquePixel = 0;
 88
 89            // Go through all rows (Y axis)
 90            for (var row = 0; row < bitmap.Height; row ++)
 91            {
 92                // Reset value
 93                colOpaquePixel = 0;
 94
 95                // Go through all columns (X axis)
 96                for (var col = 0; col < bitmap.Width; col ++)
 97                {
 98                    // If this is an opaque pixel, mark it and search for anymore trailing behind
 99                    if (bitmap.GetPixel(col, row) != colorTransparent)
100                    {
101                        // Opaque pixel found, mark current position
102                        colOpaquePixel = col;
103
104                        // create another variable to set the current pixel position
105                        var colNext = col;
106
107                        // Starting from current found opaque pixel, search for anymore opaque pixels 
108                        // trailing behind, until a transparent pixel is found or minimum width is reached
109                        for (colNext = colOpaquePixel; colNext < bitmap.Width; colNext ++)
110                            if (bitmap.GetPixel(colNext, row) == colorTransparent)
111                                break;
112
113                        // Form a rectangle for line of opaque pixels found and add it to our graphics path
114                        graphicsPath.AddRectangle(new Rectangle(colOpaquePixel, row, colNext - colOpaquePixel, 1));
115
116                        // No need to scan the line of opaque pixels just found
117                        col = colNext;
118                    }
119                }
120            }
121            // Return calculated graphics path
122            return graphicsPath;
123        }
124    }
125}