我想在进度栏上做两件事。
- 将绿色更改为红色。
- 卸下砖块,使其成为一种颜色。
我不知道如何完成有关这两件事的任何信息,我们将不胜感激!
谢谢。
我想在进度栏上做两件事。
我不知道如何完成有关这两件事的任何信息,我们将不胜感激!
谢谢。
Answers:
由于先前的答案似乎不适用于“视觉样式”。您可能需要创建自己的类或扩展进度栏:
public class NewProgressBar : ProgressBar
{
public NewProgressBar()
{
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
Rectangle rec = e.ClipRectangle;
rec.Width = (int)(rec.Width * ((double)Value / Maximum)) - 4;
if(ProgressBarRenderer.IsSupported)
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, e.ClipRectangle);
rec.Height = rec.Height - 4;
e.Graphics.FillRectangle(Brushes.Red, 2, 2, rec.Width, rec.Height);
}
}
编辑:更新的代码以使进度条使用背景的视觉样式
好的,我花了一些时间阅读所有答案和链接。这是我从他们那里得到的:
样品结果
接受的答案将禁用视觉样式,但确实允许您将颜色设置为所需的任何颜色,但结果看起来很简单:
使用以下方法,您可以得到如下所示的内容:
如何
首先,包括以下内容: using System.Runtime.InteropServices;
其次,您可以创建此新类,或将其代码放入现有的static
非泛型类中:
public static class ModifyProgressBarColor
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);
public static void SetState(this ProgressBar pBar, int state)
{
SendMessage(pBar.Handle, 1040, (IntPtr)state, IntPtr.Zero);
}
}
现在,要使用它,只需调用:
progressBar1.SetState(2);
注意SetState中的第二个参数,1 =正常(绿色);2 =错误(红色);3 =警告(黄色)。
希望能帮助到你!
public const uint PBM_SETSTATE = 0x0410; // 1040
这是最受接受的代码的无闪烁版本,您可以找到该问题的答案。所有这些都归功于这些致命答案的发布者。感谢Dusty,Chris,Matt和Josh!
就像其中一个评论中“ Fueled”的请求一样,我还需要一个表现得更...专业的版本。此代码与以前的代码一样保留样式,但是添加了屏幕外图像渲染和图形缓冲(并正确处理了图形对象)。
结果:一切正常,没有闪烁。:)
public class NewProgressBar : ProgressBar
{
public NewProgressBar()
{
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaintBackground(PaintEventArgs pevent)
{
// None... Helps control the flicker.
}
protected override void OnPaint(PaintEventArgs e)
{
const int inset = 2; // A single inset value to control teh sizing of the inner rect.
using (Image offscreenImage = new Bitmap(this.Width, this.Height))
{
using (Graphics offscreen = Graphics.FromImage(offscreenImage))
{
Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
if (ProgressBarRenderer.IsSupported)
ProgressBarRenderer.DrawHorizontalBar(offscreen, rect);
rect.Inflate(new Size(-inset, -inset)); // Deflate inner rect.
rect.Width = (int)(rect.Width * ((double)this.Value / this.Maximum));
if (rect.Width == 0) rect.Width = 1; // Can't draw rec with width of 0.
LinearGradientBrush brush = new LinearGradientBrush(rect, this.BackColor, this.ForeColor, LinearGradientMode.Vertical);
offscreen.FillRectangle(brush, inset, inset, rect.Width, rect.Height);
e.Graphics.DrawImage(offscreenImage, 0, 0);
}
}
}
}
在设计器中,您只需要将ForeColor属性设置为所需的任何颜色即可。对于红色,有一个预定义的颜色。
要在代码(C#)中执行此操作,请执行以下操作:
pgs.ForeColor = Color.Red;
编辑:是的,还将样式设置为连续。在代码中,如下所示:
pgs.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
另一个修改:您还需要删除以下内容:Application.EnableVisualStyles()
从您的Program.cs
(或类似内容)。如果您因为希望应用程序的其余部分具有视觉样式而无法执行此操作,那么我建议您自己绘制控件或继续使用WPF,因为使用WPF可以很容易地做到这一点。您可以找到有关所有者的教程,在Codeplex上绘制进度条
使用Matt Blaine和Chris Persichetti的答案,我创建了一个进度条,在允许无限的颜色选择的同时看起来更好一些(基本上我在Matt的解决方案中更改了一行):
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace QuantumConcepts.Common.Forms.UI.Controls
{
public class ProgressBarEx : ProgressBar
{
public ProgressBarEx()
{
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
LinearGradientBrush brush = null;
Rectangle rec = new Rectangle(0, 0, this.Width, this.Height);
double scaleFactor = (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum));
if (ProgressBarRenderer.IsSupported)
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rec);
rec.Width = (int)((rec.Width * scaleFactor) - 4);
rec.Height -= 4;
brush = new LinearGradientBrush(rec, this.ForeColor, this.BackColor, LinearGradientMode.Vertical);
e.Graphics.FillRectangle(brush, 2, 2, rec.Width, rec.Height);
}
}
}
progressBar.ForeColor = Color.FromArgb(255, 0, 0);
progressBar.BackColor = Color.FromArgb(150, 0, 0);
https://skydrive.live.com/?cid=0EDE5D21BDC5F270&id=EDE5D21BDC5F270%21160&sc=documents#
LinearGradientBrush
读取到Rec宽度为0 ,此代码一旦达到4就会出错。最简单的解决方法是不对代码中的4px进行“填充”,而是将其放入面板或带有填充物的面板(如果需要边框)并制作rec.Width = (int)((rec.Width * scaleFactor) - 4)
成rec.Width = (int)(rec.Width * scaleFactor) + 1
修改了dustyburwell的答案。(我没有足够的代表自己编辑它。)像他的回答一样,它启用了“视觉样式”。您可以在任何窗体的设计视图中仅设置进度条的ForeColor属性。
using System;
using System.Windows.Forms;
using System.Drawing;
public class ProgressBarEx : ProgressBar
{
private SolidBrush brush = null;
public ProgressBarEx()
{
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
if (brush == null || brush.Color != this.ForeColor)
brush = new SolidBrush(this.ForeColor);
Rectangle rec = new Rectangle(0, 0, this.Width, this.Height);
if (ProgressBarRenderer.IsSupported)
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rec);
rec.Width = (int)(rec.Width * ((double)Value / Maximum)) - 4;
rec.Height = rec.Height - 4;
e.Graphics.FillRectangle(brush, 2, 2, rec.Width, rec.Height);
}
}
我只是将其放入静态类。
const int WM_USER = 0x400;
const int PBM_SETSTATE = WM_USER + 16;
const int PBM_GETSTATE = WM_USER + 17;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
public enum ProgressBarStateEnum : int
{
Normal = 1,
Error = 2,
Paused = 3,
}
public static ProgressBarStateEnum GetState(this ProgressBar pBar)
{
return (ProgressBarStateEnum)(int)SendMessage(pBar.Handle, PBM_GETSTATE, IntPtr.Zero, IntPtr.Zero);
}
public static void SetState(this ProgressBar pBar, ProgressBarStateEnum state)
{
SendMessage(pBar.Handle, PBM_SETSTATE, (IntPtr)state, IntPtr.Zero);
}
希望能帮助到你,
马克
编辑
听起来,您正在使用XP主题,该主题具有基于绿色块的编排。尝试将UI样式翻转到Windows Classic并再次进行测试,但是您可能需要实现自己的OnPaint事件,以使其在所有UI样式中都能完成所需的工作
或者像其他人指出的那样,为您的应用程序禁用VisualStyles。
原版的
据我所知,进度栏的渲染与您选择的Windows主题样式(win2K,xp,vista)是一致的
您可以通过设置属性来更改颜色
ProgressBar.ForeColor
我不确定您还能做更多...
做一些谷歌搜索
MS KB这里有一篇有关创建“平滑”进度条的文章
尝试使用message PBM_SETBARCOLOR,应该使用SendMessage来解决问题
所有这些方法都对我不起作用,但是该方法允许您将其更改为颜色字符串。
请注意,我在StackOverflow上的其他地方找到了此代码,并对其进行了一些更改。从那以后,我忘记了在哪里找到此代码,因此无法链接它,对此感到抱歉。
但是无论如何,我希望这段代码对确实对我有帮助的人有所帮助。
private void ProgressBar_MouseDown(object sender, MouseButtonEventArgs e)
{
var converter = new System.Windows.Media.BrushConverter();
var brush = (Brush)converter.ConvertFromString("#FFB6D301");
ProgressBar.Foreground = brush;
}
如果使用名称“ ProgressBar”,请替换为您自己的进度条名称。您也可以使用其他参数触发该事件,只需确保其内括号在某处即可。
更改Color
和Value
(即时更改)
放在using System.Runtime.InteropServices;
顶部...
致电 ColorBar.SetState(progressBar1, ColorBar.Color.Yellow, myValue);
我注意到,如果您更改条形的值(它的大小),则其颜色不是默认绿色时也不会改变。我使用了user1032613的代码,并添加了Value选项。
public static class ColorBar
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr w, IntPtr l);
public enum Color { None, Green, Red, Yellow }
public static void SetState(this ProgressBar pBar, Color newColor, int newValue)
{
if (pBar.Value == pBar.Minimum) // If it has not been painted yet, paint the whole thing using defualt color...
{ // Max move is instant and this keeps the initial move from going out slowly
pBar.Value = pBar.Maximum; // in wrong color on first painting
SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero);
}
pBar.Value = newValue;
SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero); // run it out to the correct spot in default
SendMessage(pBar.Handle, 1040, (IntPtr)(int)newColor, IntPtr.Zero); // now turn it the correct color
}
}
pBar.Value = pBar.Maximum;
和SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero);
条件,身体内的以显示正确的新颜色的进展。
回答:Quote:通常,进度条是主题主题或尊重用户的颜色偏好。因此,要更改颜色,您需要关闭视觉样式并ForeColor
自己设置或绘制控件。
至于连续样式而不是块,您可以设置Style
属性:
pBar.Style = ProgressBarStyle.Continuous;
启用VistualStyles后,ProgressBarStyle.Continuous与Blocks无效。
块将仅在禁用视觉样式的情况下工作……这将使所有这些成为一个争论点(关于自定义进度颜色)在禁用现有样式的情况下……进度条应基于前景色进行着色。
我结合使用了William Daniel的答案(启用了视觉样式,因此ForeColor不会只是平坦而没有样式)和Barry的答案(用于在进度栏上自定义文本)结合使用:如何在ProgressBar上放置文本?
垂直条UP向下为红色:
using System;
using System.Windows.Forms;
using System.Drawing;
public class VerticalProgressBar : ProgressBar
{
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.Style |= 0x04;
return cp;
}
}
private SolidBrush brush = null;
public VerticalProgressBar()
{
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
if (brush == null || brush.Color != this.ForeColor)
brush = new SolidBrush(this.ForeColor);
Rectangle rec = new Rectangle(0, 0, this.Width, this.Height);
if (ProgressBarRenderer.IsSupported)
ProgressBarRenderer.DrawVerticalBar(e.Graphics, rec);
rec.Height = (int)(rec.Height * ((double)Value / Maximum)) - 4;
rec.Width = rec.Width - 4;
e.Graphics.FillRectangle(brush, 2, 2, rec.Width, rec.Height);
}
}
尊重WXP Visual Styles答案的VB.Net彩色进度条是...
我从12/3/17的“ user1032613”开始回答。请注意,这现在是一个模块,而不是一个类。从那里我转换了代码,但还需要更多。特别是,转换后的代码显示了DirectCast函数,用于将“状态”整数转换为无效的IntPtr类型。
Imports System.Runtime.InteropServices
Public Module ModifyProgressBarColor
Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=False)> _
Private Function SendMessage(hWnd As IntPtr, Msg As UInteger, w As IntPtr, l As IntPtr) As IntPtr
End Function
<System.Runtime.CompilerServices.Extension()> _
Public Sub SetState(pBar As ProgressBar, state As Integer)
'-- Convert state as integer to type IntPtr
Dim s As IntPtr
Dim y As Integer = state
s = IntPtr.op_Explicit(y)
'-- Modify bar color
SendMessage(pBar.Handle, 1040, s, IntPtr.Zero)
End Sub
End Module
再次在此行的使用代码中调用此命令:
Call ModifyProgressBarColor.SetState(prb, 2)
顺便说一句-我尝试了其他颜色-0、4、5-它们都只是显示为绿色。
我知道它的方法已经太老了,现在无法回答。但是,仍然要对@进行一些细微调整 Daniel的的答案进行以纠正不显示零值进度条的问题。仅在发现内部矩形的宽度不为零时才绘制进度。
感谢所有贡献者。
public class ProgressBarEx : ProgressBar
{
public ProgressBarEx()
{
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaintBackground(PaintEventArgs pevent){}
// None... Helps control the flicker.
protected override void OnPaint(PaintEventArgs e)
{
const int inset = 2; // A single inset value to control teh sizing of the inner rect.
using (Image offscreenImage = new Bitmap(this.Width, this.Height))
{
using (Graphics offscreen = Graphics.FromImage(offscreenImage))
{
Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
if (ProgressBarRenderer.IsSupported)
ProgressBarRenderer.DrawHorizontalBar(offscreen, rect);
rect.Inflate(new Size(-inset, -inset)); // Deflate inner rect.
rect.Width = (int)(rect.Width * ((double)this.Value / this.Maximum));
if (rect.Width != 0)
{
LinearGradientBrush brush = new LinearGradientBrush(rect, this.ForeColor, this.BackColor, LinearGradientMode.Vertical);
offscreen.FillRectangle(brush, inset, inset, rect.Width, rect.Height);
e.Graphics.DrawImage(offscreenImage, 0, 0);
offscreenImage.Dispose();
}
}
}
}
}
我发现可以通过在进度条内部绘制一个矩形并根据进度的当前值设置其宽度来完成此操作。我还添加了从右到左进度的支持。这样,您就不需要使用Image,并且由于Rectnalge.Inflate不会被调用,因此绘制的矩形会更小。
public partial class CFProgressBar : ProgressBar
{
public CFProgressBar()
{
InitializeComponent();
this.SetStyle(ControlStyles.UserPaint, true);
}
protected override void OnPaintBackground(PaintEventArgs pevent) { }
protected override void OnPaint(PaintEventArgs e)
{
double scaleFactor = (((double)Value - (double)Minimum) / ((double)Maximum - (double)Minimum));
int currentWidth = (int)((double)Width * scaleFactor);
Rectangle rect;
if (this.RightToLeftLayout)
{
int currentX = Width - currentWidth;
rect = new Rectangle(currentX, 0, this.Width, this.Height);
}
else
rect = new Rectangle(0, 0, currentWidth, this.Height);
if (rect.Width != 0)
{
SolidBrush sBrush = new SolidBrush(ForeColor);
e.Graphics.FillRectangle(sBrush, rect);
}
}
}
我认为,所有解决方案中最简单的解决方案只是一个快速解决方案,但是您可以从Program.cs中删除Application.EnableVisualStyles()并对其添加注释,也可以将包含Main函数的部分命名为。之后,您可以通过progressBar.ForeColor = Color.TheColorYouDesire;从进度条自由更改颜色。
static void Main()
{
//Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
编辑:在两个分钟中,我花了点时间启动vs并检查了我被打败的语法,并给出了更好的响应。我喜欢这个网站。
progressBar1 = new ProgressBar();
progressBar1.ForeColor = Color.Red;