Управление индикатором выполнения WPF из приложения WinForms - PullRequest
0 голосов
/ 27 мая 2020

У меня есть приложение WinForms, созданное с использованием vb. net, в которое я добавил пользовательский элемент управления WPF. Пользовательский элемент управления WPF состоит только из индикатора выполнения. Я могу перетащить элемент управления WPF из панели инструментов и добавить его в основную форму в WinForms vb. net. Но я не знаю, как разрешить моему приложению WinForms динамически устанавливать значение для индикатора выполнения WPF. В любом случае я могу динамически установить значение индикатора выполнения элемента управления WPF из моего приложения WinForms?

Примечание. Причина, по которой я использую индикатор выполнения WPF вместо индикатора выполнения WinForms, заключается в том, что я могу иметь синий индикатор выполнения в моем приложении WinForms.

1 Ответ

1 голос
/ 28 мая 2020

Поскольку это может быть не так просто, как может выглядеть на бумаге, вот настраиваемый ProgressBar, который позволяет установить цвет полосы, а также изменить ее стиль на лету .

Свойство ProgressBarStyle устанавливает текущий стиль: стиль BarStyle.Standard использует метод ProgressBarRenderer.DrawHorizontalBar () для рисования своего background, в то время как BarStyle.Flat выбирает Parent.BackColor в качестве цвета фона и использует фиксированную белую границу для рисования границ ProgressBar и SystemColors.Highlight как цвет полосы. Конечно, его можно изменить для поддержки любого другого цвета и стандартного стиля.

Класс StringFormat используется для центрирования текста ProgressBar (только в стиле Standard. Его также можно легко изменить), задав для горизонтального и вертикального выравнивания значение StringAlignment.Center .
Цвет текста изменяется автоматически для адаптации к яркости цвета ProgressBar (это всего лишь простая настройка, значение HSL само по себе не всегда может определить, какой цвет текста лучше соответствует цвету фона).

Некоторые magi c значения - это просто смещения, используемые для адаптации прямоугольников чертежа к формам, разработанным ProgressBarRenderer


Вот как это работает :

ProgressBar Custom

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# версия:

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