Chciałbym zrobić dwie rzeczy na pasku postępu.
- Zmień kolor zielony na czerwony.
- 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.
Chciałbym zrobić dwie rzeczy na pasku postępu.
Wszelkie informacje na temat tych dwóch rzeczy, które zastanawiam się, jak osiągnąć, będą bardzo mile widziane!
Dzięki.
Odpowiedzi:
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
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:
Korzystając z następującej metody, możesz zamiast tego uzyskać coś takiego:
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 static
klasie 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!
public const uint PBM_SETSTATE = 0x0410; // 1040
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);
}
}
}
}
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
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):
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
odczytanie 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
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);
}
}
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
Zwykle pasek postępu ma motyw lub jest zgodny z preferencjami kolorystycznymi użytkownika. Aby zmienić kolor, musisz albo wyłączyć style wizualne i ForeColor
samodzielnie ustawić lub narysować kontrolkę.
Jeśli chodzi o styl ciągły zamiast bloków, możesz ustawić Style
właściwość:
pBar.Style = ProgressBarStyle.Continuous;
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
spróbuj użyć messsage PBM_SETBARCOLOR, co powinno załatwić sprawę z SendMessage
Zobacz przykład http://www.vbforums.com/showthread.php?t=248721 .
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.
Zmień Color
i 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
}
}
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.
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ć.
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 ForeColor
samodzielnie ustawić lub narysować kontrolkę.
Jeśli chodzi o styl ciągły zamiast bloków, możesz ustawić Style
wł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?
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);
}
}
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.
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();
}
}
}
}
}
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);
}
}
}
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());
}
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;