Jak zmienić kolor paska postępu w C # .NET 3.5?

92

Chciałbym zrobić dwie rzeczy na pasku postępu.

  1. Zmień kolor zielony na czerwony.
  2. Usuń klocki i zrób to w jednym kolorze.

Wszelkie informacje na temat tych dwóch rzeczy, które zastanawiam się, jak osiągnąć, będą bardzo mile widziane!

Dzięki.

Ivan Prodanov
źródło

Odpowiedzi:

83

Ponieważ poprzednie odpowiedzi nie działają ze stylami wizualnymi. Prawdopodobnie będziesz musiał stworzyć własną klasę lub rozszerzyć pasek postępu:

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

EDYCJA: Zaktualizowano kod, aby pasek postępu używał stylu wizualnego dla tła

Chris Persichetti
źródło
2
Dzięki za to, to było coś, nad czym mogłem pracować w moim rozwiązaniu.
Irwin
To naprawdę fajne, dzięki. Naprawdę pomogło mi to w czymś, nad czym w tej chwili pracuję, chociaż zmieniłem to, aby za każdym razem przemalować całą kontrolkę zamiast tylko obszaru określonego przez e.ClipRectangle. W przeciwnym razie nie malował poprawnie po tym, jak tylko część formantu została unieważniona przez inne okno lub krawędź ekranu.
Matt Blaine
@Matt Blaine: Czy mógłbyś opublikować swoją modyfikację jako edycję odpowiedzi? Wierzę, że będzie wystarczająco dużo osób zainteresowanych Twoim kompletnym rozwiązaniem.
Marek
@Marek Właśnie zauważyłem Twój komentarz. Nie mam wystarczającej liczby powtórzeń, aby edytować odpowiedź, więc opublikowałem własne. Dzięki. stackoverflow.com/questions/778678/…
Matt Blaine
3
Zdaję sobie sprawę, że to jest stare; i zdaję sobie sprawę, że to jest nuta (ponieważ Minimum prawie zawsze wynosi zero); ale współczynnik skali szerokości powinien wynosić (((podwójna) wartość - (podwójna) minimalna) / ((podwójna) maksymalna - (podwójna) minimalna)), aby była poprawna z retencją analną. :)
Jesse Chisholm
122

OK, przeczytanie wszystkich odpowiedzi i linków zajęło mi trochę czasu. Oto, co z nich wyciągnąłem:

Przykładowe wyniki

Zaakceptowana odpowiedź wyłącza style wizualne, pozwala ustawić dowolny kolor, ale wynik wygląda prosto:

wprowadź opis obrazu tutaj

Korzystając z następującej metody, możesz zamiast tego uzyskać coś takiego:

wprowadź opis obrazu tutaj

Jak

Po pierwsze, dołącz to, jeśli nie masz: using System.Runtime.InteropServices;

Po drugie, możesz albo utworzyć tę nową klasę, albo umieścić jej kod w istniejącej staticklasie nieogólnej:

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

Teraz, aby z niego skorzystać, wystarczy zadzwonić:

progressBar1.SetState(2);

Zwróć uwagę na drugi parametr w SetState, 1 = normal (zielony); 2 = błąd (czerwony); 3 = ostrzeżenie (żółty).

Mam nadzieję, że to pomoże!

user1032613
źródło
18
Utworzyłeś metodę rozszerzającą, więc wywołanie powinno mieć postać progressBar1.SetState (2); poza tym Świetna odpowiedź!
Edgar Hernandez,
5
Należy zauważyć, że jest to dostępne tylko w systemie Vista +. Pełną dokumentację można wyświetlić, wyszukując PBM_SETSTATE .
Djof
Piękny! Dziękuję
sapbucket
1
To niesamowite, ale częściowo łamie mój pasek postępu, nigdy nie zapełni się w 100% ...
Norbert Boros
1
public const uint PBM_SETSTATE = 0x0410; // 1040
Andrei Krasutski
37

To jest wolna od migotania wersja najczęściej akceptowanego kodu, który można znaleźć jako odpowiedzi na to pytanie. Cała zasługa plakatów z tymi fatalnymi odpowiedziami. Dzięki, Dusty, Chris, Matt i Josh!

Podobnie jak prośba „Fueled” w jednym z komentarzy, potrzebowałem wersji, która zachowywałaby się nieco bardziej ... profesjonalnie. Ten kod zachowuje style jak w poprzednim kodzie, ale dodaje renderowanie obrazu poza ekranem i buforowanie grafiki (i prawidłowo usuwa obiekt graficzny).

Wynik: wszystko dobrze i bez migotania. :)

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);
            }
        }
    }
}
Williama Daniela
źródło
Cóż, jest to najbliższe oryginalnej implementacji firmy Microsoft.
Yakup Ünyılmaz
1
Posiadanie using bloku i wywoływanie Dispose jest w rzeczywistości trochę zbędne. Świetna odpowiedź.
Kevin Stricker
1
Zdaję sobie sprawę, że to jest stare; i zdaję sobie sprawę, że to jest nuta (ponieważ Minimum prawie zawsze wynosi zero); ale współczynnik skali szerokości powinien wynosić (((podwójna) wartość - (podwójna) minimalna) / ((podwójna) maksymalna - (podwójna) minimalna)), aby była poprawna z retencją analną. :)
Jesse Chisholm
Kiedy używam TextRenderer.DrawText () do rysowania tekstu na obrazie poza ekranem, końcowy wynik na ekranie wygląda na pikselowany, a nie jak etykieta używająca dokładnie tej samej czcionki. Rysowanie tego wszystkiego bezpośrednio do e.Graphics bez offscreenimagera daje jednak poprawny wynik ... Jakieś pomysły dlaczego?
CuriousGeorge,
1
Tak, próbowałem śpiewać bez skalowania. W końcu właśnie przeszedłem na WPF, więc wszystko, czego potrzebuję, jest wbudowane.
CuriousGeorge
28

W projektancie wystarczy ustawić właściwość ForeColor na dowolny kolor. W przypadku czerwieni jest to wstępnie zdefiniowany kolor.

Aby to zrobić w kodzie (C #), wykonaj następujące czynności:

pgs.ForeColor = Color.Red;

Edycja : O tak, ustaw również styl na ciągły. W kodzie, na przykład:

pgs.Style = System.Windows.Forms.ProgressBarStyle.Continuous;

Kolejna edycja: musisz również usunąć wiersz, który czyta Application.EnableVisualStyles()z twojego Program.cs(lub podobnego). Jeśli nie możesz tego zrobić, ponieważ chcesz, aby reszta aplikacji miała style wizualne, sugerowałbym samodzielne malowanie kontrolki lub przejście do WPF, ponieważ tego rodzaju rzeczy są łatwe w WPF. Możesz znaleźć samouczek dotyczący rysowania paska postępu przez właściciela w Codeplex

dustyburwell
źródło
3
Forecolor = czerwony; Backcolor = niebieski; Styl = ciągły. Nic się nie zmieniło, pozostało tak, jakbym go nigdy nie dotykał
Ivan Prodanov
3
ba ... okej, widzę problem. Musisz wyłączyć style wizualne, aby działało to z właściwościami. Prawdopodobnie jest to malowanie przy użyciu dowolnego wybranego motywu. W Program.cs znajduje się wiersz, który czyta Application.EnableVisualStyles (). Usuń tę linię i to zadziała. W przeciwnym razie musisz samodzielnie pomalować kontrolkę. Inną opcją jest użycie WPF (jeśli to możliwe), ponieważ pozwala to naprawdę łatwo robić tego rodzaju rzeczy.
dustyburwell
Proszę o więcej informacji na temat „Jak samemu to pomalować”.
Ivan Prodanov
1
Oto samouczek dotyczący rysowania paska postępu przez właściciela. Ten proces jest zbyt skomplikowany, aby móc komentować. codeproject.com/KB/cpp/VistaProgressBar.aspx
dustyburwell
1
Szkoda, że ​​Application.EnableVisualStyles () jest kluczową częścią tego rozwiązania. Niestety to łamie wszystkie inne style.
mr.user1065741
16

Korzystając z odpowiedzi Matta Blaine'a i Chrisa Persichetti, stworzyłem pasek postępu, który wygląda trochę ładniej, jednocześnie pozwalając na nieskończony wybór kolorów (w zasadzie zmieniłem jedną linię w rozwiązaniu Matta):

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

Stosowanie:

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

Wyniki

Możesz użyć dowolnego gradientu, który Ci się podoba!

Pobieranie

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

Josh M.
źródło
2
Zdaję sobie sprawę, że to jest stare; i zdaję sobie sprawę, że to jest nuta (ponieważ Minimum prawie zawsze wynosi zero); ale współczynnik skali szerokości powinien wynosić (((podwójna) wartość - (podwójna) minimalna) / ((podwójna) maksymalna - (podwójna) minimalna)), aby była poprawna z retencją analną. :)
Jesse Chisholm
Zaktualizowałem odpowiedź z twoją sugestią.
Josh M.
Wiem, że jest stary, ale - ten kod wyświetli błąd, gdy osiągnie wartość 4, ze względu na LinearGradientBrushodczytanie szerokości nagrywania jako 0. Najłatwiejszym rozwiązaniem jest pominięcie „dopełnienia” 4 pikseli w kodzie i zamiast tego umieszczenie go w panel lub coś z wyściółką (jeśli chcesz granicę) i co rec.Width = (int)((rec.Width * scaleFactor) - 4)dorec.Width = (int)(rec.Width * scaleFactor) + 1
MiDri
14

Modyfikacja odpowiedzi Dustyburwella. (Nie mam wystarczającej liczby powtórzeń, aby samodzielnie to edytować.) Podobnie jak jego odpowiedź, działa z włączonymi „Stylami wizualnymi”. Możesz po prostu ustawić właściwość ForeColor paska postępu w dowolnym widoku projektu formularza.

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);
    }
}
Matt Blaine
źródło
Działa to świetnie do zmiany koloru pierwszego planu, ale bardzo migocze, podczas gdy domyślna kontrolka ProgressBar nie. Masz jakiś pomysł, jak to rozwiązać?
Zasilany
4
Dowiedziałem się, jak rozwiązać problem migotania: dodaj podwójne buforowanie do ControlStyles zdefiniowanego przez użytkownika ProgressBar, na przykład: SetStyle (ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, ...).
Zasilany
Zdaję sobie sprawę, że to jest stare; i zdaję sobie sprawę, że to jest nuta (ponieważ Minimum prawie zawsze wynosi zero); ale współczynnik skali szerokości powinien wynosić (((podwójna) wartość - (podwójna) minimalna) / ((podwójna) maksymalna - (podwójna) minimalna)), aby była poprawna z retencją analną. :)
Jesse Chisholm
5

Po prostu umieściłem to w klasie statycznej.

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

Mam nadzieję, że to pomoże,

Marc

Marc
źródło
+1: Myślę, że to właśnie większość ludzi miała na myśli mówiąc o czerwieni. Pokazuje stan błędu.
kwantowy
3

Zwykle pasek postępu ma motyw lub jest zgodny z preferencjami kolorystycznymi użytkownika. Aby zmienić kolor, musisz albo wyłączyć style wizualne i ForeColorsamodzielnie ustawić lub narysować kontrolkę.

Jeśli chodzi o styl ciągły zamiast bloków, możesz ustawić Stylewłaściwość:

pBar.Style = ProgressBarStyle.Continuous;
Joey
źródło
2

EDYTOWAĆ

Według dźwięków rzeczy, których używasz motywu XP, który ma pasek progowy oparty na zielonym bloku. Spróbuj zmienić styl interfejsu użytkownika na klasyczny Windows i przetestuj ponownie, ale może być konieczne zaimplementowanie własnego zdarzenia OnPaint, aby uzyskać to, co chcesz, we wszystkich stylach interfejsu użytkownika

Lub, jak ktoś wskazał, wyłącz VisualStyles dla swojej aplikacji.

Oryginał

O ile wiem, renderowanie paska postępu odbywa się zgodnie z wybranym stylem motywu systemu Windows (win2K, xp, vista)

Możesz zmienić kolor, ustawiając właściwość

ProgressBar.ForeColor

Nie jestem jednak pewien, czy możesz zrobić znacznie więcej ...

trochę googluje

Tutaj jest artykuł z MS KB na temat tworzenia „gładkiego” paska postępu

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

Eoin Campbell
źródło
@ Eion, Forecolor = czerwony; Backcolor = niebieski; Styl = ciągły. Nic się nie zmieniło, pozostaje jakbym go nigdy nie dotykał.
Ivan Prodanov
2

Wszystkie te metody nie działają dla mnie, ale ta metoda pozwala zmienić ją na ciąg kolorów.

Zwróć uwagę, że znalazłem ten kod z innego miejsca w StackOverflow i trochę go zmieniłem. Od tego czasu zapomniałem, gdzie znalazłem ten kod i nie mogę go połączyć z tego powodu, przepraszam za to.

Ale w każdym razie mam nadzieję, że ten kod komuś pomógł.

private void ProgressBar_MouseDown(object sender, MouseButtonEventArgs e)
    {
        var converter = new System.Windows.Media.BrushConverter();
        var brush = (Brush)converter.ConvertFromString("#FFB6D301");
        ProgressBar.Foreground = brush;
    }

Tam, gdzie jest używana nazwa „ProgressBar”, zastąp własną nazwą paska postępu. Możesz również wywołać to zdarzenie za pomocą innych argumentów, po prostu upewnij się, że jest gdzieś wewnątrz nawiasów.

EpicNinjaCheese
źródło
niezła robota… używam wewnątrz zdarzenia ProgressChanged, aby przejść od jasnego do ciemnego ... + 1
BENN1TH
2

Zmień Colori Value(natychmiastowa zmiana)

Umieść using System.Runtime.InteropServices;na górze ...

Zadzwoń z ColorBar.SetState(progressBar1, ColorBar.Color.Yellow, myValue);

Zauważyłem, że jeśli zmienisz wartość paska (jak duży jest), to nie zmieni się, jeśli będzie w kolorze innym niż domyślny zielony. Wziąłem kod user1032613 i dodałem opcję Wartość.

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
    }

}
Sparfy
źródło
2
Mieliśmy do przerzucania pBar.Value = pBar.Maximum;i SendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero);wnętrza stan-ciała dla postępu, aby pokazać prawidłową nowy kolor.
DomTheDeveloper
1

Na wszelki wypadek, gdyby ktoś szukał innej opcji ... możesz rozszerzyć Panel, użyć go jako tła (białego lub innego), dodać kolejny Panel w nim jako pierwszy plan (ruchomy pasek). Wtedy masz całkowitą kontrolę nad zmianą koloru itp.

Eduardo
źródło
1

Po prostu kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań języka Visual Basic (gdzie znajdują się pliki vb) i wybierz właściwości z menu. W oknie, które się pojawi, usuń zaznaczenie „Włącz style wizualne XP”, a teraz, kiedy ustawisz kolor forecolor, powinno to teraz działać.

Krzykliwy
źródło
0

Tak: Cytat: Zazwyczaj pasek postępu jest tematyczny lub zgodny z preferencjami kolorystycznymi użytkownika. Aby zmienić kolor, musisz albo wyłączyć style wizualne i ForeColorsamodzielnie ustawić lub narysować kontrolkę.

Jeśli chodzi o styl ciągły zamiast bloków, możesz ustawić Stylewłaściwość:

pBar.Style = ProgressBarStyle.Continuous;

ProgressBarStyle.Continuous versus Blocks jest bezużyteczne z włączonymi VistualStyles ...

Bloki będą działać tylko przy wyłączonych stylach wizualnych ... co czyni to wszystko kwestią sporną (w odniesieniu do niestandardowego koloru postępu) Przy wyłączonych stylach wizualnych ... pasek postępu powinien być pokolorowany na podstawie koloru podstawowego.

Użyłem kombinacji odpowiedzi Williama Daniela (z włączonymi stylami wizualnymi, więc ForeColor nie będzie po prostu płaska bez stylu) i odpowiedzi Barry'ego (do niestandardowego tekstu na pasku postępu) z: Jak umieścić tekst na ProgressBar?

NeoH4x0r
źródło
0

Pionowy pasek w górę w dół w kolorze czerwonym:

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

    } 
}
Mandrova
źródło
Czy możesz wyjaśnić w tekście lub w komentarzach do kodu, jak to rozwiązuje problem.
Harrison
Zdaję sobie sprawę, że to nuta (ponieważ Minimum prawie zawsze wynosi zero); ale współczynnik skali wysokości powinien wynosić (((podwójna) wartość - (podwójna) minimalna) / ((podwójna) maksymalna - (podwójna) minimalna)), aby była poprawna z retencją analną. :)
Jesse Chisholm
0

Kolorowy pasek postępu VB.Net, który odpowiada stylom wizualnym WXP, to ...

Zacząłem od odpowiedzi od „user1032613” w dniu 17.03.12. Zauważ, że jest to teraz moduł, a nie klasa. Stamtąd przekonwertowałem kod, ale potrzeba było więcej. W szczególności przekonwertowany kod pokazał funkcję DirectCast do konwersji liczby całkowitej „stanu” na typ IntPtr, który nie działał.

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

I znowu po prostu wywołaj to w kodzie using za pomocą tej linii:

Call ModifyProgressBarColor.SetState(prb, 2)

Przy okazji - próbowałem innych kolorów - 0, 4, 5 - wszystkie były po prostu zielone.

DanW52
źródło
0

Wiem, że jest zbyt stary, by teraz odpowiedzieć… ale mimo to mała poprawka do odpowiedzi @ Daniela w celu rozwiązania problemu braku wyświetlania paska postępu o zerowej wartości. Po prostu narysuj Progress tylko wtedy, gdy szerokość wewnętrznego prostokąta jest różna od zera.

Podziękowania dla wszystkich współpracowników.

        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();
                        }
                    }
                }
            }
        }
Divins Mathew
źródło
0

Odkryłem, że można to zrobić, rysując prostokąt wewnątrz paska postępu i ustawiając jego szerokość zgodnie z bieżącą wartością postępu. Dodałem również obsługę postępu od prawej do lewej. W ten sposób nie musisz używać Image, a ponieważ Rectnalge.Inflate nie jest nazywane, to narysowany prostokąt jest mniejszy.

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);
        }
    }
}
ZOK
źródło
0

Myślę, że najprostsze rozwiązania ze wszystkich, to tylko szybka naprawa, ale możesz usunąć, skomentować Application.EnableVisualStyles () z Program.cs, lub jakkolwiek nazwać swoją część zawierającą funkcję Main. Następnie możesz dowolnie zmieniać kolor z paska postępu przez progressBar.ForeColor = Color.TheColorYouDesire;

static void Main()
        {
            //Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
         }
Mladen Tasevski
źródło
-5

Edycja: w dwóch menu zajęło mi uruchomienie vs i sprawdzenie składni, w której zostałem pobity z dużo lepszymi odpowiedziami. uwielbiam tę stronę.

        progressBar1 = new ProgressBar();
        progressBar1.ForeColor = Color.Red;
Fusspawn
źródło
2
Nie działa, jest teraz pusty, dodałem progressBar1.value = 50, ale nadal pusty
Ivan Prodanov
próbowałeś ustawić maksymalną wartość? progressBar1 = nowy ProgressBar (); progressBar1.ForeColor = Color.Red; progressBar1.Maximum = 100;
Fusspawn
2
Nie, problem dotyczy motywu mojego systemu Windows.
Ivan Prodanov
Nie mam pojęcia, czy to zadziała, ale spróbuj wykomentować Application.EnableVisualThemes (); czyli w jednym z gotowych plików w porównaniu z generatorem (nie mogę sobie przypomnieć, który)
Fusspawn
1
Application.EnableVisualStyles () przepraszam, nie motywy
Fusspawn