从WinForms应用程序控制WPF进度栏 [英] Control WPF progress bar from WinForms app
问题描述
我有一个用vb .net构建的WinForms应用程序,并向其中添加了WPF用户控件.WPF用户控件仅包含一个进度条.我可以将WPF控件从toolbax拖动到WinForms vb .net中的Main Form中.但是我不知道如何让我的WinForms应用程序动态设置WPF进度栏的值.无论如何,我可以从WinForms应用程序动态设置WPF控件进度栏的值吗?
注意:我使用WPF进度条而不使用WinForms进度条的原因是为了使我可以在WinForms应用程序中使用蓝色的进度条.
由于它可能不像在纸上看起来那样简单,因此这里有一个自定义的ProgressBar,它可以设置条形的颜色并更改其样式即时.
ProgressBarStyle
属性设置当前样式: BarStyle.Standard
样式使用
自定义控件的VB.Net版本:
导入System.ComponentModel导入System.Drawing.Drawing2D导入System.Drawing导入System.Windows.Forms< DesignerCategory(代码")>公共类ProgressBarCustomColor继承ProgressBar私有m_ParentBackColor为Color = SystemColors.Window私有m_ProgressBarStyle为BarStyle = BarStyle.Standard私人m_FlatBorderColor为Color = Color.White公开子New()SetStyle(ControlStyles.AllPaintingInWmPaint或ControlStyles.UserPaint或ControlStyles.OptimizedDoubleBuffer,True)结束子公共枚举BarStyle标准平坦的结束枚举公共属性ProgressBarStyle作为BarStyle得到返回m_ProgressBarStyle结束获取放m_ProgressBarStyle =值如果是DesignMode,则Me.Parent?.Refresh()端套最终财产公共属性FlatBorderColor作为颜色得到返回m_FlatBorderColor结束获取放m_FlatBorderColor =值如果是DesignMode,则Me.Parent?.Refresh()端套最终财产受保护的重写Sub OnParentChanged(例如EventArgs)MyBase.OnParentChanged(e)m_ParentBackColor = If(Me.Parent不算什么,Me.Parent.BackColor,SystemColors.Window)结束子受保护的重写Sub OnPaintBackground(例如,作为PaintEventArgs)MyBase.OnPaintBackground(e)暗淡= Me.ClientRectangle如果m_ProgressBarStyle = BarStyle.Standard,则ProgressBarRenderer.DrawHorizontalBar(e.Graphics,rect)Dim baseColor = Color.FromArgb(240,Me.BackColor)昏暗的highColor = Color.FromArgb(160,baseColor)使用baseBrush = New SolidBrush(baseColor),highBrush =新的SolidBrush(highColor)e.Graphics.FillRectangle(highBrush,1,2,rect.Width,9)e.Graphics.FillRectangle(baseBrush,1,7,rect.Width,rect.Height-1)最终使用别的使用pen =新Pen(m_FlatBorderColor,2),baseBrush =新的SolidBrush(m_ParentBackColor)e.Graphics.FillRectangle(baseBrush,0,0,矩形宽度-1,矩形高度-1)e.Graphics.DrawRectangle(pen,1,1,Me.ClientSize.Width-2,Me.ClientSize.Height-2)最终使用万一结束子受保护的重写Sub OnPaint(e作为PaintEventArgs)Dim rect =新RectangleF(PointF.Empty,Me.ClientSize)rect.Width = CType(rect.Width *(CType(Me.Value,Single)/Me.Maximum),Integer)rect.Size =新的SizeF(rect.Width-2,rect.Height)Dim hsl as Single = Me.ForeColor.GetBrightness()如果m_ProgressBarStyle = BarStyle.Standard,则DrawStandardBar(e.Graphics,rect,hsl)如果m_ProgressBarStyle = BarStyle.Flat,则DrawFlatBar(e.Graphics,rect,hsl)结束子私有子DrawStandardBar(g作为图形,rect作为RectangleF,hsl作为单个)g.SmoothingMode = SmoothingMode.AntiAliasg.CompositingQuality = CompositingQuality.HighQualityDim baseColor = Color.FromArgb(240,Me.ForeColor)昏暗的highColor = Color.FromArgb(160,baseColor)使用baseBrush = New SolidBrush(baseColor),highBrush =新的SolidBrush(highColor),sf = New StringFormat(StringFormatFlags.MeasureTrailingSpaces)sf.LineAlignment = StringAlignment.Centersf.Alignment = StringAlignment.Centerg.FillRectangle(highBrush,1,2,rect.Width,9)g.FillRectangle(baseBrush,1,7,rect.Width,rect.Height-1)g.DrawString($"{Me.Value}%",Me.Parent.Font,如果(hsl> 0.49F,Brushes.Black,Brushes.White),Me.ClientRectangle,sf)最终使用结束子私有子DrawFlatBar(g作为图形,rect作为RectangleF,hsl作为单个)使用baseBrush = New SolidBrush(SystemColors.Highlight)g.FillRectangle(baseBrush,2,2,rect.Width-2,rect.Height-4)最终使用结束子末级
C#版本:
使用System.ComponentModel;使用System.Drawing;使用System.Drawing.Drawing2D;使用System.Windows.Forms;[DesignerCategory(代码")]公共类ProgressBarCustomColor:ProgressBar{私人颜色m_ParentBackColor = SystemColors.Window;私人颜色m_FlatBorderColor = Color.White;私人BarStyle m_ProgressBarStyle = BarStyle.Standard;公共ProgressBarCustomColor(){this.SetStyle(ControlStyles.AllPaintingInWmPaint |ControlStyles.UserPaint |ControlStyles.OptimizedDoubleBuffer,true);}公共枚举BarStyle {Standard,Flat}公共BarStyle ProgressBarStyle {得到=>m_ProgressBarStyle;放 {m_ProgressBarStyle =值;如果(DesignMode)this.Parent?.Refresh();}}公共颜色FlatBorderColor {得到=>m_FlatBorderColor;放 {m_FlatBorderColor =值;如果(DesignMode)this.Parent?.Refresh();}}受保护的重写void OnParentChanged(EventArgs e){base.OnParentChanged(e);m_ParentBackColor = this.Parent?.BackColor?SystemColors.Window;}受保护的重写void OnPaintBackground(PaintEventArgs e){base.OnPaintBackground(e);var rect = this.ClientRectangle;如果(m_ProgressBarStyle == BarStyle.Standard){ProgressBarRenderer.DrawHorizontalBar(e.Graphics,rect);var baseColor = Color.FromArgb(240,this.BackColor);var highColor = Color.FromArgb(160,baseColor);使用(var baseBrush = new SolidBrush(baseColor))使用(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);}}别的 {使用(var pen = new Pen(m_FlatBorderColor,2))使用(var baseBrush = new SolidBrush(m_ParentBackColor)){e.Graphics.FillRectangle(baseBrush,0,0,矩形宽度-1,矩形高度-1);e.Graphics.DrawRectangle(pen,1,1,this.ClientSize.Width-2,this.ClientSize.Height-2);}}}受保护的重写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();如果(m_ProgressBarStyle == BarStyle.Standard)DrawStandardBar(e.Graphics,rect,hsl);如果(m_ProgressBarStyle == BarStyle.Flat)DrawFlatBar(e.Graphics,rect,hsl);}私有无效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);使用(var baseBrush = new SolidBrush(baseColor))使用(var highBrush = new SolidBrush(highColor))使用(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);}}私有void DrawFlatBar(图形g,RectangleF rect,float hsl){使用(var baseBrush = new SolidBrush(SystemColors.Highlight)){g.FillRectangle(baseBrush,2,2,rect.Width-2,rect.Height-4);}}}
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.
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);
}
}
}
这篇关于从WinForms应用程序控制WPF进度栏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!