Control WPF progress bar from WinForms app

不打扰是莪最后的温柔 提交于 2021-02-11 15:46:48

问题


I have an WinForms app built with vb .net to which I've added a WPF user control. The WPF user control consists of only a progressbar. I can drag the WPF control from the toolbax and add it to the Main Form in WinForms vb .net. But I don't know how to let my WinForms app dynamically set the value for the WPF progress bar. Anyway I can dynamically set the WPF control progress bar's value from my WinForms app?

Note: The reason Im using WPF progress bar instead of using WinForms progress bar is so that I can have blue colored progress bar in my WinForms app.


回答1:


Since it may not be as straightforward as it may look like on paper, here's a custom ProgressBar that allows to set the Color of the bar and also change its style on the fly.

The ProgressBarStyle property sets the current style: the BarStyle.Standard style uses the ProgressBarRenderer.DrawHorizontalBar() method to draw its background, while the BarStyle.Flat selects the Parent.BackColor as background color and uses a fixed white border to draw the ProgressBar bounds and SystemColors.Highlight as the bar color. Of course it can be changed to support any other color and the Standard style.

The StringFormat class is used to center the text of the ProgressBar (in Standard style only. This can also be easily changed), setting both Horizontal and Vertical alignment to StringAlignment.Center.
The text color changes automatically to adapt to the Brightness of the ProgressBar color (it's just a simple adjustment, the HSL value on its own cannot always determine what text color better fits a background color).

Some magic values are just offsets used to adapt the drawing rectangles to the shapes designed by ProgressBarRenderer


This is how it works:

VB.Net version of the Custom Control:

Imports System.ComponentModel
Imports System.Drawing.Drawing2D
Imports System.Drawing
Imports System.Windows.Forms

<DesignerCategory("Code")>
Public Class ProgressBarCustomColor
    Inherits ProgressBar

    Private m_ParentBackColor As Color = SystemColors.Window
    Private m_ProgressBarStyle As BarStyle = BarStyle.Standard
    Private m_FlatBorderColor As Color = Color.White

    Public Sub New()
        SetStyle(ControlStyles.AllPaintingInWmPaint Or
                 ControlStyles.UserPaint Or
                 ControlStyles.OptimizedDoubleBuffer, True)
    End Sub

    Public Enum BarStyle
        Standard
        Flat
    End Enum

    Public Property ProgressBarStyle As BarStyle
        Get
            Return m_ProgressBarStyle
        End Get
        Set
            m_ProgressBarStyle = Value
            If DesignMode Then Me.Parent?.Refresh()
        End Set
    End Property

    Public Property FlatBorderColor As Color
        Get
            Return m_FlatBorderColor
        End Get
        Set
            m_FlatBorderColor = Value
            If DesignMode Then Me.Parent?.Refresh()
        End Set
    End Property

    Protected Overrides Sub OnParentChanged(e As EventArgs)
        MyBase.OnParentChanged(e)
        m_ParentBackColor = If(Me.Parent IsNot Nothing, Me.Parent.BackColor, SystemColors.Window)
    End Sub

    Protected Overrides Sub OnPaintBackground(e As PaintEventArgs)
        MyBase.OnPaintBackground(e)
        Dim rect = Me.ClientRectangle

        If m_ProgressBarStyle = BarStyle.Standard Then
            ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rect)

            Dim baseColor = Color.FromArgb(240, Me.BackColor)
            Dim highColor = Color.FromArgb(160, baseColor)
            Using baseBrush = New SolidBrush(baseColor),
                  highBrush = New SolidBrush(highColor)
                e.Graphics.FillRectangle(highBrush, 1, 2, rect.Width, 9)
                e.Graphics.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1)
            End Using
        Else
            Using pen = New Pen(m_FlatBorderColor, 2),
                  baseBrush = New SolidBrush(m_ParentBackColor)
                e.Graphics.FillRectangle(baseBrush, 0, 0, rect.Width - 1, rect.Height - 1)
                e.Graphics.DrawRectangle(pen, 1, 1, Me.ClientSize.Width - 2, Me.ClientSize.Height - 2)
            End Using
        End If
    End Sub

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        Dim rect = New RectangleF(PointF.Empty, Me.ClientSize)
        rect.Width = CType(rect.Width * (CType(Me.Value, Single) / Me.Maximum), Integer)
        rect.Size = New SizeF(rect.Width - 2, rect.Height)

        Dim hsl As Single = Me.ForeColor.GetBrightness()
        If m_ProgressBarStyle = BarStyle.Standard Then DrawStandardBar(e.Graphics, rect, hsl)
        If m_ProgressBarStyle = BarStyle.Flat Then DrawFlatBar(e.Graphics, rect, hsl)
    End Sub

    Private Sub DrawStandardBar(g As Graphics, rect As RectangleF, hsl As Single)
        g.SmoothingMode = SmoothingMode.AntiAlias
        g.CompositingQuality = CompositingQuality.HighQuality

        Dim baseColor = Color.FromArgb(240, Me.ForeColor)
        Dim highColor = Color.FromArgb(160, baseColor)

        Using baseBrush = New SolidBrush(baseColor),
              highBrush = New SolidBrush(highColor),
              sf = New StringFormat(StringFormatFlags.MeasureTrailingSpaces)
            sf.LineAlignment = StringAlignment.Center
            sf.Alignment = StringAlignment.Center

            g.FillRectangle(highBrush, 1, 2, rect.Width, 9)
            g.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1)
            g.DrawString($"{Me.Value} %", Me.Parent.Font,
                If(hsl > 0.49F, Brushes.Black, Brushes.White), Me.ClientRectangle, sf)
        End Using
    End Sub

    Private Sub DrawFlatBar(g As Graphics, rect As RectangleF, hsl As Single)
        Using baseBrush = New SolidBrush(SystemColors.Highlight)
            g.FillRectangle(baseBrush, 2, 2, rect.Width - 2, rect.Height - 4)
        End Using
    End Sub
End Class

C# version:

using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

[DesignerCategory("Code")]
public class ProgressBarCustomColor : ProgressBar
{
    private Color m_ParentBackColor = SystemColors.Window;
    private Color m_FlatBorderColor = Color.White;
    private BarStyle m_ProgressBarStyle = BarStyle.Standard;
    public ProgressBarCustomColor()
    {
        this.SetStyle(
            ControlStyles.AllPaintingInWmPaint | 
            ControlStyles.UserPaint | 
            ControlStyles.OptimizedDoubleBuffer, true);
    }

    public enum BarStyle { Standard, Flat }

    public BarStyle ProgressBarStyle {
        get => m_ProgressBarStyle;
        set {
            m_ProgressBarStyle = value;
            if (DesignMode) this.Parent?.Refresh();
        }
    }

    public Color FlatBorderColor {
        get => m_FlatBorderColor;
        set {
            m_FlatBorderColor = value;
            if (DesignMode) this.Parent?.Refresh();
        }
    }

    protected override void OnParentChanged(EventArgs e)
    {
        base.OnParentChanged(e);
        m_ParentBackColor = this.Parent?.BackColor ?? SystemColors.Window;
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        base.OnPaintBackground(e);
        var rect = this.ClientRectangle;

        if (m_ProgressBarStyle == BarStyle.Standard) {
            ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rect);

            var baseColor = Color.FromArgb(240, this.BackColor);
            var highColor = Color.FromArgb(160, baseColor);
            using (var baseBrush = new SolidBrush(baseColor))
            using (var highBrush = new SolidBrush(highColor)) {
                e.Graphics.FillRectangle(highBrush, 1, 2, rect.Width, 9);
                e.Graphics.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1);
            }
        }
        else {
            using (var pen = new Pen(m_FlatBorderColor, 2))
            using (var baseBrush = new SolidBrush(m_ParentBackColor)) {
                e.Graphics.FillRectangle(baseBrush, 0, 0, rect.Width - 1, rect.Height - 1);
                e.Graphics.DrawRectangle(pen, 1, 1, this.ClientSize.Width - 2, this.ClientSize.Height - 2);
            }
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        var rect = new RectangleF(PointF.Empty, this.ClientSize);
        rect.Width = (int)(rect.Width * ((float)this.Value / this.Maximum));
        rect.Size = new SizeF(rect.Width - 2, rect.Height);

        float hsl = this.ForeColor.GetBrightness();
        if (m_ProgressBarStyle == BarStyle.Standard) DrawStandardBar(e.Graphics, rect, hsl);
        if (m_ProgressBarStyle == BarStyle.Flat) DrawFlatBar(e.Graphics, rect, hsl);
    }

    private void DrawStandardBar(Graphics g, RectangleF rect, float hsl)
    {
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.CompositingQuality = CompositingQuality.HighQuality;

        var baseColor = Color.FromArgb(240, this.ForeColor);
        var highColor = Color.FromArgb(160, baseColor);

        using (var baseBrush = new SolidBrush(baseColor))
        using (var highBrush = new SolidBrush(highColor))
        using (var sf = new StringFormat(StringFormatFlags.MeasureTrailingSpaces)) {
            sf.LineAlignment = StringAlignment.Center;
            sf.Alignment = StringAlignment.Center;

            g.FillRectangle(highBrush, 1, 2, rect.Width, 9);
            g.FillRectangle(baseBrush, 1, 7, rect.Width, rect.Height - 1);
            g.DrawString($"{this.Value} %", this.Parent.Font, 
                hsl > .49f ? Brushes.Black : Brushes.White, this.ClientRectangle, sf);
        }
    }

    private void DrawFlatBar(Graphics g, RectangleF rect, float hsl)
    {
        using (var baseBrush = new SolidBrush(SystemColors.Highlight)) {
            g.FillRectangle(baseBrush, 2, 2, rect.Width - 2, rect.Height - 4);
        }
    }
}


来源:https://stackoverflow.com/questions/62043526/control-wpf-progress-bar-from-winforms-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!