我希望在我的进度条上做两件事情。
- 将绿色改为红色。
- 移除方块并将其变成单一颜色。
如何实现这两个目标的任何信息都将不胜感激!
谢谢。
好的,我花了一些时间阅读所有的答案和链接。以下是我从中得到的内容:
示例结果
被接受的答案禁用了视觉样式,它确实允许你将颜色设置为任何你想要的,但结果看起来很简单:
使用以下方法,您可以获得类似于这样的内容:如何操作
首先,如果您还没有,请包含以下内容: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 = 警告(黄色)
。由于之前的答案似乎在 Visual Styles 中不起作用。你可能需要创建自己的类或扩展进度条:
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);
}
}
编辑:更新代码,使进度条使用视觉样式作为背景
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
属性设置为您想要的任何颜色即可。对于红色,有一个预定义的颜色。pgs.ForeColor = Color.Red;
编辑:对了,还要将样式设置为continuous
。在代码中,像这样:
pgs.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
另一个编辑:你还需要从你的Program.cs
(或类似文件)中删除一行代码Application.EnableVisualStyles()
。如果你不能这样做,因为你希望应用程序的其余部分具有视觉样式,那么我建议你自己绘制控件,或者转向使用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。最简单的解决方法是在代码中不要进行4px的“填充”,而是将其放置在带有填充的面板或其他容器中(如果您想要边框),并将rec.Width = (int)((rec.Width * scaleFactor) - 4)
更改为rec.Width = (int)(rec.Width * scaleFactor) + 1
。 - MiDri对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);
}
ForeColor
或自己绘制控件。Style
属性:pBar.Style = ProgressBarStyle.Continuous;
更改颜色和值(即时更改)
在顶部添加using System.Runtime.InteropServices;
使用ColorBar.SetState(progressBar1, ColorBar.Color.Yellow, myValue);
进行调用
我注意到如果您更改进度条的值(大小),则如果它处于除默认绿色外的其他颜色,则不会更改。我采用了user1032613的代码并添加了一个值选项。
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);
翻转到条件体内部,以便进度条显示正确的新颜色。 - DomTheDeveloperProgressBar.ForeColor
public const uint PBM_SETSTATE = 0x0410; // 1040
- Andrei Krasutski