简体   繁体   English

从 WinForms 应用程序控制 WPF 进度条

[英]Control WPF progress bar from WinForms app

I have an WinForms app built with vb .net to which I've added a WPF user control.我有一个用 vb .net 构建的 WinForms 应用程序,我在其中添加了一个 WPF 用户控件。 The WPF user control consists of only a progressbar. WPF 用户控件仅包含一个进度条。 I can drag the WPF control from the toolbax and add it to the Main Form in WinForms vb .net.我可以从工具箱中拖动 WPF 控件并将其添加到 WinForms vb .net 的主窗体中。 But I don't know how to let my WinForms app dynamically set the value for the WPF progress bar.但我不知道如何让我的 WinForms 应用程序动态设置 WPF 进度条的值。 Anyway I can dynamically set the WPF control progress bar's value from my WinForms app?无论如何,我可以从我的 WinForms 应用程序动态设置 WPF 控制进度条的值吗?

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.注意:我使用 WPF 进度条而不是使用 WinForms 进度条的原因是我可以在我的 WinForms 应用程序中使用蓝色进度条。

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 .由于它可能不像纸上看起来那么简单,这里有一个自定义的 ProgressBar,它允许设置栏的颜色并动态更改其样式

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. ProgressBarStyle属性设置当前样式: BarStyle.Standard样式使用ProgressBarRenderer.DrawHorizontalBar()方法绘制其背景,而BarStyle.Flat选择Parent.BackColor作为背景颜色并使用固定的白色边框绘制 ProgressBar 边界和SystemColors.Highlight作为条形颜色。 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 . StringFormat class 用于将 ProgressBar 的文本居中(仅限Standard样式。这也可以轻松更改),将水平和垂直 alignment 设置为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).文本颜色会自动更改以适应 ProgressBar 颜色的亮度(这只是一个简单的调整, HSL值本身并不能始终确定哪种文本颜色更适合背景颜色)。

Some magic values are just offsets used to adapt the drawing rectangles to the shapes designed by ProgressBarRenderer一些魔法值只是用于使绘图矩形适应ProgressBarRenderer设计的形状的偏移量


This is how it works :这是它的工作原理

进度条自定义

VB.Net version of the Custom Control: VB.Net 版本的自定义控件:

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: C#版本:

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);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM