Tôi muốn làm hai việc trên thanh tiến trình của mình.
- Thay đổi màu xanh lá cây thành màu đỏ.
- Loại bỏ các khối và làm cho nó bằng một màu.
Bất kỳ thông tin nào về hai điều đó mà tôi tự hỏi làm thế nào để hoàn thành sẽ rất hốc hác!
Cảm ơn.
Tôi muốn làm hai việc trên thanh tiến trình của mình.
Bất kỳ thông tin nào về hai điều đó mà tôi tự hỏi làm thế nào để hoàn thành sẽ rất hốc hác!
Cảm ơn.
Câu trả lời:
Vì các câu trả lời trước dường như không hoạt động với Visual Styles. Có thể bạn sẽ cần tạo lớp của riêng mình hoặc mở rộng thanh tiến trình:
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);
}
}
CHỈNH SỬA: Mã đã cập nhật để làm cho thanh tiến trình sử dụng kiểu trực quan cho nền
OK, tôi đã mất một lúc để đọc tất cả các câu trả lời và liên kết. Đây là những gì tôi nhận được từ chúng:
Kết quả mẫu
Câu trả lời được chấp nhận sẽ vô hiệu hóa các kiểu trực quan, nó cho phép bạn đặt màu thành bất kỳ thứ gì bạn muốn, nhưng kết quả trông đơn giản:
Sử dụng phương pháp sau, bạn có thể nhận được một cái gì đó như thế này thay thế:
Làm thế nào để
Đầu tiên, hãy bao gồm điều này nếu bạn chưa: using System.Runtime.InteropServices;
Thứ hai, bạn có thể tạo lớp mới này hoặc đặt mã của nó vào một static
lớp không chung chung hiện có :
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);
}
}
Bây giờ, để sử dụng nó, chỉ cần gọi:
progressBar1.SetState(2);
Lưu ý tham số thứ hai trong SetState, 1 = normal (màu xanh lá cây); 2 = lỗi (đỏ); 3 = cảnh báo (màu vàng).
Hy vọng nó giúp!
public const uint PBM_SETSTATE = 0x0410; // 1040
Đây là phiên bản không nhấp nháy của mã được chấp nhận nhiều nhất mà bạn có thể tìm thấy như câu trả lời cho câu hỏi này. Tất cả tín dụng cho áp phích của những câu trả lời châm biếm đó. Cảm ơn Dusty, Chris, Matt và Josh!
Giống như yêu cầu của "Fueled" trong một trong các nhận xét, tôi cũng cần một phiên bản hoạt động ... chuyên nghiệp hơn một chút. Mã này duy trì các kiểu như trong mã trước, nhưng thêm kết xuất hình ảnh ngoài màn hình và bộ đệm đồ họa (và bố trí đối tượng đồ họa đúng cách).
Kết quả: tất cả đều tốt và không có hiện tượng nhấp nháy. :)
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);
}
}
}
}
Trong trình thiết kế, bạn chỉ cần đặt thuộc tính ForeColor thành bất kỳ màu nào bạn muốn. Trong trường hợp của Màu đỏ, có một màu được xác định trước cho nó.
Để làm điều đó trong mã (C #), hãy làm như sau:
pgs.ForeColor = Color.Red;
Chỉnh sửa : Ồ đúng rồi, cũng đặt Kiểu thành liên tục. Trong mã, như thế này:
pgs.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
Chỉnh sửa khác: Bạn cũng sẽ cần xóa dòng đọc Application.EnableVisualStyles()
khỏi Program.cs
(hoặc tương tự) của bạn. Nếu bạn không thể làm điều này vì bạn muốn phần còn lại của ứng dụng có phong cách trực quan, thì tôi khuyên bạn nên tự sơn điều khiển hoặc chuyển sang WPF vì loại việc này rất dễ dàng với WPF. Bạn có thể tìm thấy một hướng dẫn về chủ sở hữu vẽ một thanh tiến trình trên codeplex
Sử dụng câu trả lời của Matt Blaine và Chris Persichetti, tôi đã tạo một thanh tiến trình trông đẹp hơn một chút trong khi cho phép lựa chọn màu vô hạn (về cơ bản tôi đã thay đổi một dòng trong giải pháp của 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
đọc chiều rộng rec là 0. Cách khắc phục dễ nhất là không thực hiện "padding" 4px trong mã và thay vào đó hãy đặt nó vào một bảng điều khiển hoặc thứ gì đó có đệm (nếu bạn muốn có đường viền) và tạo rec.Width = (int)((rec.Width * scaleFactor) - 4)
thànhrec.Width = (int)(rec.Width * scaleFactor) + 1
Modificaton cho câu trả lời của Dustburwell. (Tôi không có đủ đại diện để tự chỉnh sửa.) Giống như câu trả lời của anh ấy, nó hoạt động với "Kiểu trực quan" được bật. Bạn chỉ có thể đặt thuộc tính ForeColor của thanh tiến trình trong bất kỳ dạng xem thiết kế nào của biểu mẫu.
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);
}
}
Tôi chỉ đặt cái này vào một lớp tĩnh.
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);
}
Hy vọng nó giúp,
Marc
Thông thường, thanh tiến trình có chủ đề hoặc tôn vinh sở thích màu sắc của người dùng. Vì vậy, để thay đổi màu sắc, bạn cần phải tắt các kiểu trực quan và tự thiết lập ForeColor
hoặc vẽ điều khiển.
Đối với kiểu liên tục thay vì khối, bạn có thể đặt thuộc Style
tính:
pBar.Style = ProgressBarStyle.Continuous;
BIÊN TẬP
Bằng âm thanh của những thứ bạn đang sử dụng Chủ đề XP có thanh prog dựa trên khối màu xanh lá cây. Hãy thử chuyển Kiểu giao diện người dùng của bạn sang Windows Classic và thử nghiệm lại, nhưng bạn có thể cần phải triển khai sự kiện OnPaint của riêng mình để làm cho nó làm những gì bạn muốn trên tất cả các Kiểu giao diện người dùng
Hoặc như ai đó đã chỉ ra, hãy tắt VisualStyles cho ứng dụng của bạn.
Nguyên
Theo như tôi biết, việc hiển thị thanh Tiến trình xảy ra nội tuyến với phong cách chủ đề cửa sổ mà bạn đã chọn (win2K, xp, vista)
Bạn có thể thay đổi màu bằng cách đặt thuộc tính
ProgressBar.ForeColor
Tuy nhiên, tôi không chắc rằng bạn có thể làm được nhiều hơn thế nữa ...
có một số googling
Có một bài viết ở đây từ MS KB về cách tạo thanh tiến trình "Smooth"
hãy thử sử dụng messsage PBM_SETBARCOLOR, điều đó sẽ thực hiện thủ thuật với SendMessage
Xem http://www.vbforums.com/showthread.php?t=248721 để làm ví dụ.
Tất cả các phương pháp này không hoạt động đối với tôi nhưng phương pháp này cho phép bạn thay đổi nó thành một chuỗi màu.
Xin lưu ý rằng tôi đã tìm thấy mã này từ một nơi khác trên StackOverflow và đã thay đổi nó một chút. Tôi đã quên nơi tôi tìm thấy mã này và tôi không thể liên kết nó vì điều đó rất tiếc cho điều đó.
Nhưng dù sao tôi hy vọng mã này sẽ giúp ai đó nó thực sự đã giúp tôi.
private void ProgressBar_MouseDown(object sender, MouseButtonEventArgs e)
{
var converter = new System.Windows.Media.BrushConverter();
var brush = (Brush)converter.ConvertFromString("#FFB6D301");
ProgressBar.Foreground = brush;
}
Trường hợp tên "ProgressBar" được sử dụng thay thế bằng tên thanh tiến trình của riêng bạn. Bạn cũng có thể kích hoạt sự kiện này với các đối số khác chỉ cần đảm bảo rằng bên trong dấu ngoặc nhọn của nó ở đâu đó.
Thay đổi Color
và Value
(thay đổi tức thì)
Đặt using System.Runtime.InteropServices;
ở đầu ...
Gọi với ColorBar.SetState(progressBar1, ColorBar.Color.Yellow, myValue);
Tôi nhận thấy rằng nếu bạn thay đổi giá trị của thanh (nó lớn như thế nào) thì nó sẽ không thay đổi nếu nó có màu khác với màu xanh lá cây mặc định. Tôi đã lấy mã của user1032613 và thêm tùy chọn Giá trị.
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;
và SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero);
bên trong của phần thân điều kiện để tiến trình hiển thị màu mới chính xác.
Chỉ trong trường hợp có ai đó tìm kiếm một tùy chọn khác .... bạn có thể mở rộng một Bảng điều khiển, sử dụng nó làm nền (màu trắng hoặc bất cứ thứ gì), thêm một Bảng điều khiển khác bên trong nó cho nền trước (thanh di chuyển). Sau đó, bạn có toàn quyền kiểm soát việc thay đổi màu sắc, v.v.
Јοеу: Trích dẫn: Thông thường thanh tiến trình có chủ đề hoặc tôn vinh sở thích màu sắc của người dùng. Vì vậy, để thay đổi màu sắc, bạn cần phải tắt các kiểu trực quan và tự thiết lập ForeColor
hoặc vẽ điều khiển.
Đối với kiểu liên tục thay vì khối, bạn có thể đặt thuộc Style
tính:
pBar.Style = ProgressBarStyle.Continuous;
ProgressBarStyle.Contin liên tục so với Blocks là vô dụng với VistualStyles được bật ...
(Các) khối sẽ chỉ hoạt động với các kiểu hình ảnh bị vô hiệu hóa ... điều này làm cho tất cả những điều này trở thành điểm tranh luận (liên quan đến màu tiến trình tùy chỉnh) Với các kiểu thực tế bị tắt ... thanh tiến trình sẽ được tô màu dựa trên màu nền.
Tôi đã sử dụng kết hợp câu trả lời của William Daniel (đã bật kiểu trực quan, vì vậy ForeColor sẽ không chỉ phẳng mà không có kiểu) và câu trả lời của Barry (cho văn bản tùy chỉnh trên thanh tiến trình) từ: Làm cách nào để đặt văn bản trên ProgressBar?
Thanh dọc LÊN Để Xuống màu đỏ:
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);
}
}
Thanh tiến trình màu VB.Net tôn trọng câu trả lời của WXP Visual Styles là ...
Tôi bắt đầu với câu trả lời từ 'user1032613' vào ngày 17/3/12. Lưu ý rằng đây bây giờ là một Mô-đun, không phải một lớp. Từ đó tôi đã chuyển đổi mã nhưng cần nhiều hơn thế. Đặc biệt, mã được chuyển đổi cho thấy một chức năng DirectCast để chuyển đổi số nguyên 'trạng thái' thành một loại IntPtr không hoạt động.
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
Và một lần nữa, chỉ cần gọi điều này trong mã sử dụng với dòng này:
Call ModifyProgressBarColor.SetState(prb, 2)
BTW - Tôi đã thử các màu khác - 0, 4, 5 - tất cả chúng chỉ hiển thị màu xanh lá cây.
Tôi biết cách này đã quá cũ để được trả lời bây giờ .. nhưng vẫn còn, một chỉnh sửa nhỏ cho câu trả lời của @ Daniel để khắc phục vấn đề không hiển thị thanh tiến trình có giá trị bằng không. Chỉ vẽ Tiến trình chỉ khi chiều rộng của hình chữ nhật bên trong được tìm thấy là khác 0.
Cảm ơn tất cả những người đã đóng góp.
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();
}
}
}
}
}
Tôi thấy điều này có thể được thực hiện bằng cách vẽ một hình chữ nhật bên trong thanh tiến trình và đặt chiều rộng của nó theo giá trị hiện tại của tiến trình. Tôi cũng hỗ trợ thêm cho tiến trình từ phải sang trái. Bằng cách này, bạn không cần sử dụng Image và vì Rectnalge.Inflate không được gọi là hình chữ nhật được vẽ nhỏ hơn.
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);
}
}
}
Tôi nghĩ rằng các giải pháp đơn giản nhất, đó chỉ là một bản sửa lỗi nhanh chóng, nhưng bạn có thể xóa, nhận xét Application.EnableVisualStyles () khỏi Program.cs, hoặc tuy nhiên, bạn đặt tên cho phần chứa Hàm chính. Sau đó, bạn có thể tự do thay đổi hình thức màu sắc của thanh tiến trình bằng ProgressBar.ForeColor = Color.TheColorYouDesire;
static void Main()
{
//Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
Chỉnh sửa: trong hai minuites, tôi đã phải khởi động và kiểm tra cú pháp, tôi đã bị đánh bại với nó với phản hồi tốt hơn nhiều. tôi thích trang web này.
progressBar1 = new ProgressBar();
progressBar1.ForeColor = Color.Red;