public override void DrawProgressBar (Graphics dc, Rectangle clip_rect, ProgressBar ctrl) { if (!RenderClientAreas || !VisualStyleRenderer.IsElementDefined (VisualStyleElement.ProgressBar.Bar.Normal) || !VisualStyleRenderer.IsElementDefined (VisualStyleElement.ProgressBar.Chunk.Normal)) { base.DrawProgressBar (dc, clip_rect, ctrl); return; } VisualStyleRenderer renderer = new VisualStyleRenderer (VisualStyleElement.ProgressBar.Bar.Normal); renderer.DrawBackground (dc, ctrl.ClientRectangle, clip_rect); Rectangle client_area = renderer.GetBackgroundContentRectangle (dc, new Rectangle (Point.Empty, ctrl.Size)); renderer = new VisualStyleRenderer (VisualStyleElement.ProgressBar.Chunk.Normal); /* Draw Blocks */ int draw_mode = 0; int max_blocks = int.MaxValue; int start_pixel = client_area.X; #if NET_2_0 draw_mode = (int)ctrl.Style; #endif switch (draw_mode) { #if NET_2_0 case 1: // Continuous client_area.Width = (int)(client_area.Width * ((double)(ctrl.Value - ctrl.Minimum) / (double)(Math.Max (ctrl.Maximum - ctrl.Minimum, 1)))); renderer.DrawBackground (dc, client_area, clip_rect); break; case 2: // Marquee int ms_diff = (int)(DateTime.Now - ctrl.start).TotalMilliseconds; double percent_done = (double)ms_diff % (double)ctrl.MarqueeAnimationSpeed / (double)ctrl.MarqueeAnimationSpeed; max_blocks = 5; start_pixel = client_area.X + (int)(client_area.Width * percent_done); goto default; #endif default: // Blocks int block_width = renderer.GetInteger (IntegerProperty.ProgressChunkSize); block_width = Math.Max (block_width, 0); // block_width is used to break out the loop below, it must be >= 0! int first_pixel_outside_filled_area = (int)(((double)(ctrl.Value - ctrl.Minimum) * client_area.Width) / (Math.Max (ctrl.Maximum - ctrl.Minimum, 1))) + client_area.X; int block_count = 0; int increment = block_width + renderer.GetInteger (IntegerProperty.ProgressSpaceSize); Rectangle block_rect = new Rectangle (start_pixel, client_area.Y, block_width, client_area.Height); while (true) { if (max_blocks != int.MaxValue) { if (block_count == max_blocks) break; if (block_rect.Right >= client_area.Width) block_rect.X -= client_area.Width; } else { if (block_rect.X >= first_pixel_outside_filled_area) break; if (block_rect.Right >= first_pixel_outside_filled_area) if (first_pixel_outside_filled_area == client_area.Right) block_rect.Width = first_pixel_outside_filled_area - block_rect.X; else break; } if (clip_rect.IntersectsWith (block_rect)) renderer.DrawBackground (dc, block_rect, clip_rect); block_rect.X += increment; block_count++; } break; } }
/// <summary> /// Gets the background image of the current visual style element within the specified background color. If <paramref name="states"/> is set, the resulting image will contain each of the state images side by side. /// </summary> /// <param name="rnd">The <see cref="VisualStyleRenderer"/> instance.</param> /// <param name="clr">The background color. This color cannot have an alpha channel.</param> /// <param name="states">The optional list of states to render side by side.</param> /// <returns>The background image.</returns> public static Bitmap GetBackgroundBitmap(this VisualStyleRenderer rnd, Color clr, int[] states = null) { const int wh = 200; if (rnd == null) { throw new ArgumentNullException(nameof(rnd)); } rnd.SetParameters(rnd.Class, rnd.Part, 0); if (states == null) { states = new[] { rnd.State } } ; var i = states.Length; // Get image size Size imgSz; using (var sg = Graphics.FromHwnd(IntPtr.Zero)) imgSz = rnd.GetPartSize(sg, new Rectangle(0, 0, wh, wh), ThemeSizeType.Draw); if (imgSz.Width == 0 || imgSz.Height == 0) { imgSz = new Size(rnd.GetInteger(IntegerProperty.Width), rnd.GetInteger(IntegerProperty.Height)); } var bounds = new Rectangle(0, 0, imgSz.Width * i, imgSz.Height); // Draw each background linearly down the bitmap using (var memoryHdc = SafeDCHandle.ScreenCompatibleDCHandle) { // Create a device-independent bitmap and select it into our DC var info = new BITMAPINFO(bounds.Width, -bounds.Height); IntPtr ppv; using (new SafeDCObjectHandle(memoryHdc, CreateDIBSection(SafeDCHandle.Null, ref info, DIBColorMode.DIB_RGB_COLORS, out ppv, IntPtr.Zero, 0))) { using (var memoryGraphics = Graphics.FromHdc(memoryHdc.DangerousGetHandle())) { // Setup graphics memoryGraphics.CompositingMode = CompositingMode.SourceOver; memoryGraphics.CompositingQuality = CompositingQuality.HighQuality; memoryGraphics.SmoothingMode = SmoothingMode.HighQuality; memoryGraphics.Clear(clr); // Draw each background linearly down the bitmap var rect = new Rectangle(0, 0, imgSz.Width, imgSz.Height); foreach (var state in states) { rnd.SetParameters(rnd.Class, rnd.Part, state); rnd.DrawBackground(memoryGraphics, rect); rect.X += imgSz.Width; } } // Copy DIB to Bitmap var bmp = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb); using (var primaryHdc = new SafeDCHandle(Graphics.FromImage(bmp))) BitBlt(primaryHdc, bounds.Left, bounds.Top, bounds.Width, bounds.Height, memoryHdc, 0, 0, RasterOperationMode.SRCCOPY); return(bmp); } } }