Làm cách nào để thay đổi màu của thanh tiến trình trong C # .NET 3.5?


92

Tôi muốn làm hai việc trên thanh tiến trình của mình.

  1. Thay đổi màu xanh lá cây thành màu đỏ.
  2. 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.

Câu trả lời:


83

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


2
Cảm ơn vì điều này, đó là thứ mà tôi có thể làm việc với giải pháp của mình.
Irwin

Điều đó thực sự tuyệt vời, cảm ơn. Nó thực sự giúp tôi giải quyết được điều gì đó mà tôi đang làm vào lúc này, mặc dù tôi đã thay đổi nó để sơn lại toàn bộ điều khiển mỗi lần thay vì chỉ khu vực được chỉ định bởi e.ClipRectangle. Nếu không, nó sẽ không sơn lại chính xác sau khi chỉ một phần của điều khiển bị vô hiệu bởi cửa sổ khác hoặc cạnh của màn hình.
Matt Blaine,

@Matt Blaine: Bạn có thể vui lòng đăng sửa đổi của mình dưới dạng chỉnh sửa cho câu trả lời không? Tôi tin rằng sẽ có đủ người quan tâm đến giải pháp hoàn chỉnh của bạn.
Marek

@Marek Chỉ cần nhận thấy bình luận của bạn. Tôi không có đủ đại diện để chỉnh sửa câu trả lời, vì vậy tôi đã đăng của riêng tôi. Cảm ơn. stackoverflow.com/questions/778678/…
Matt Blaine

3
Tôi nhận ra điều này đã cũ; và tôi nhận ra đây là một nit (vì Tối thiểu gần như luôn luôn bằng 0); nhưng hệ số tỷ lệ Chiều rộng phải là (((gấp đôi) Giá trị - (gấp đôi) Tối thiểu) / (gấp đôi) Tối đa - (gấp đôi) Tối thiểu)) thì mới chính xác. :)
Jesse Chisholm

122

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:

nhập mô tả hình ảnh ở đây

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ế:

nhập mô tả hình ảnh ở đây

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 staticlớ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!


18
Bạn đã tạo một phương thức mở rộng, vì vậy cuộc gọi phải là processBar1.SetState (2); ngoài ra từ đó, câu trả lời tuyệt vời!
Edgar Hernandez

5
Cần lưu ý rằng điều này chỉ khả dụng trên Vista +. Bạn có thể xem toàn bộ tài liệu bằng cách tìm kiếm PBM_SETSTATE .
Djof

Xinh đẹp! Cảm ơn bạn
sapbucket

1
Điều này thật tuyệt vời, nhưng nó phá vỡ thanh tiến trình của tôi một phần, nó sẽ không bao giờ đầy 100% ....
Norbert Boros

1
public const uint PBM_SETSTATE = 0x0410; // 1040
Andrei Krasutski

37

Đâ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);
            }
        }
    }
}

Đây là cách gần nhất với lời tuyên bố ban đầu từ Microsoft.
Yakup Ünyılmaz

1
Có một khối using gọi Dispose thực sự hơi thừa. Câu trả lời tuyệt vời mặc dù.
Kevin Stricker

1
Tôi nhận ra điều này đã cũ; và tôi nhận ra đây là một nit (vì Tối thiểu gần như luôn luôn bằng 0); nhưng hệ số tỷ lệ Chiều rộng phải là (((gấp đôi) Giá trị - (gấp đôi) Tối thiểu) / (gấp đôi) Tối đa - (gấp đôi) Tối thiểu)) thì mới chính xác. :)
Jesse Chisholm

Khi tôi sử dụng TextRenderer.DrawText () để vẽ văn bản thành các chi tiết nhỏ, kết quả cuối cùng trên màn hình trông giống như màu trắng và không giống như một nhãn sử dụng cùng một phông chữ. Việc vẽ tất cả những điều này trực tiếp cho e.Graphics mà không có người phụ trách sẽ đưa ra kết quả chính xác mặc dù ... Bất kỳ ý tưởng nào tại sao?
CuriousGeorge

1
Vâng, tôi đã thử đánh dấu không theo tỷ lệ. Cuối cùng, tôi chỉ chuyển sang WPF, vì vậy tất cả những gì cần thiết chỉ được xây dựng trong.
CuriousGeorge

28

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


3
Forecolor = đỏ; Backcolor = xanh lam; Phong cách = Continious. Không có gì thay đổi, ở lại nó giống như tôi không bao giờ chạm vào nó
Ivan Prodanov

3
bah ... được rồi, tôi thấy có vấn đề. Bạn cần tắt kiểu trực quan để kiểu này hoạt động với các thuộc tính. Nó có thể là bức tranh sử dụng bất kỳ chủ đề nào bạn đã chọn. Trong Program.cs có một dòng ghi Application.EnableVisualStyles (). Loại bỏ dòng đó và điều này sẽ hoạt động. Nếu không, bạn sẽ cần tự sơn điều khiển. Tùy chọn khác là sử dụng WPF (nếu có thể), vì nó cho phép bạn thực hiện loại công việc này thực sự dễ dàng.
Dustburwell

Xin vui lòng cho tôi biết thêm thông tin về "Làm thế nào để vẽ nó một mình".
Ivan Prodanov

1
Đây là hướng dẫn về cách chủ sở hữu vẽ thanh tiến trình. Quá trình này quá phức tạp cho một nhận xét. codeproject.com/KB/cpp/VistaProgressBar.aspx
Dustburwell

1
Thật đáng tiếc khi Application.EnableVisualStyles () là phần quan trọng của giải pháp này. Thật không may, điều này phá vỡ tất cả các phong cách khác.
mr.user1065741

16

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):

ProgressBarEx:

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

Sử dụng:

progressBar.ForeColor = Color.FromArgb(255, 0, 0);
progressBar.BackColor = Color.FromArgb(150, 0, 0);

Các kết quả

Bạn có thể sử dụng bất kỳ gradient nào bạn thích!

Tải xuống

https://skydrive.live.com/?cid=0EDE5D21BDC5F270&id=EDE5D21BDC5F270%21160&sc=documents#


2
Tôi nhận ra điều này đã cũ; và tôi nhận ra đây là một nit (vì Tối thiểu hầu như luôn luôn bằng 0); nhưng hệ số tỷ lệ Chiều rộng phải là (((gấp đôi) Giá trị - (gấp đôi) Tối thiểu) / (gấp đôi) Tối đa - (gấp đôi) Tối thiểu)) thì mới chính xác. :)
Jesse Chisholm

Đã cập nhật câu trả lời với gợi ý của bạn.
Josh M.

Tôi biết nó đã cũ, nhưng - mã này sẽ lỗi khi nó đạt đến giá trị 4, do 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
MiDri

14

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

Điều này hoạt động tuyệt vời để thay đổi màu nền trước, nhưng nó nhấp nháy rất nhiều, trong khi điều khiển ProgressBar mặc định thì không. Bất kỳ ý tưởng làm thế nào để giải quyết điều này?
Được tiếp nhiên liệu

4
Tôi đã tìm ra cách giải quyết hiện tượng nhấp nháy: thêm bộ đệm kép vào ControlStyles của ProgressBar do người dùng xác định, như sau: SetStyle (ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, ...).
Được tiếp nhiên liệu

Tôi nhận ra điều này đã cũ; và tôi nhận ra đây là một nit (vì Tối thiểu hầu như luôn luôn bằng 0); nhưng hệ số tỷ lệ Chiều rộng phải là (((gấp đôi) Giá trị - (gấp đôi) Tối thiểu) / (gấp đôi) Tối đa - (gấp đôi) Tối thiểu)) thì mới chính xác. :)
Jesse Chisholm

5

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


+1: Tôi nghĩ rằng đây là ý nghĩa của hầu hết mọi người về màu đỏ. Làm cho nó hiển thị trạng thái lỗi.
quantum

3

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 ForeColorhoặ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 Styletính:

pBar.Style = ProgressBarStyle.Continuous;

2

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"

http://support.microsoft.com/kb/323116


@ Eion, Forecolor = đỏ; Backcolor = xanh lam; Phong cách = Continious. Không có gì thay đổi, nó ở lại như thể tôi chưa từng chạm vào nó.
Ivan Prodanov


2

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 đó.


Làm tốt lắm..Tôi đang sử dụng bên trong sự kiện ProgressChanged để chuyển từ sáng sang tối ... + 1
BENN1TH

2

Thay đổi ColorValue(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
    }

}

2
Chúng tôi phải lật pBar.Value = pBar.Maximum;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.
DomTheDeveloper

1

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.


1

Chỉ cần nhấp chuột phải vào dự án của bạn trong Visual Basic Solution Explorer (nơi chứa tệp vb của bạn) và chọn thuộc tính từ menu. Trong cửa sổ bật lên, hãy bỏ chọn "Bật Kiểu Hình ảnh XP" và bây giờ khi bạn đặt màu ngoại hình, nó sẽ hoạt động ngay bây giờ.


0

Јοеу: 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 ForeColorhoặ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 Styletí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?


0

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

    } 
}

Bạn có thể vui lòng giải thích bằng văn bản hoặc trong nhận xét cho mã cách này giải quyết vấn đề không.
Harrison

Tôi nhận ra đây là một nit (vì Tối thiểu gần như luôn luôn bằng không); nhưng hệ số thang đo Chiều cao phải là ((gấp đôi) Giá trị - (gấp đôi) Tối thiểu) / (gấp đôi) Tối đa - (gấp đôi) Tối thiểu)) để chính xác. :)
Jesse Chisholm

0

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.


0

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

0

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

0

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

-5

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;

2
Không work.It ở lại trống rỗng bây giờ, tôi thêm progressBar1.value = 50, nhưng vẫn trống rỗng
Ivan Prodanov

đã thử đặt giá trị maxiumum? ProgressBar1 = new ProgressBar (); ProgressBar1.ForeColor = Color.Red; ProgressBar1.Maximum = 100;
Fusspawn

2
Không, vấn đề là ở chủ đề cửa sổ của tôi.
Ivan Prodanov

Không biết điều này có hiệu quả hay không, nhưng hãy thử bình luận Application.EnableVisualThemes (); đó là một trong các file được xây dựng sẵn vs tạo của (I cant nhớ lại những gì một)
Fusspawn

1
Application.EnableVisualStyles () xin lỗi không phải chủ đề
Fusspawn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.