จะเปลี่ยนสีของแถบความคืบหน้าใน C # .NET 3.5 ได้อย่างไร?


92

ฉันต้องการทำสองสิ่งบนแถบความคืบหน้า

  1. เปลี่ยนสีเขียวเป็นสีแดง
  2. นำบล็อกออกและทำให้เป็นสีเดียว

ข้อมูลใด ๆ เกี่ยวกับสองสิ่งที่ฉันสงสัยว่าจะทำอย่างไรให้สำเร็จจะเป็นที่ชื่นชอบ

ขอบคุณ.

คำตอบ:


83

เนื่องจากคำตอบก่อนหน้าดูเหมือนจะไม่สามารถใช้ได้กับ 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);
    }
}

แก้ไข: อัปเดตโค้ดเพื่อให้แถบความคืบหน้าใช้รูปแบบภาพสำหรับพื้นหลัง


2
ขอบคุณสำหรับสิ่งนี้มันเป็นสิ่งที่ฉันสามารถใช้แก้ปัญหาได้
เออร์วิน

เยี่ยมจริงๆขอบคุณ มันช่วยฉันได้มากในบางสิ่งที่ฉันกำลังทำอยู่ในขณะนี้แม้ว่าฉันจะเปลี่ยนเป็นการทาสีการควบคุมทั้งหมดทุกครั้งแทนที่จะเป็นเพียงพื้นที่ที่ e.ClipRectangle ระบุ มิฉะนั้นจะไม่ทาสีใหม่อย่างถูกต้องหลังจากที่ส่วนควบคุมเพียงบางส่วนถูกหน้าต่างอื่นหรือขอบของหน้าจอใช้
Matt Blaine

@ Matt Blaine: คุณช่วยโพสต์การแก้ไขของคุณเป็นการแก้ไขคำตอบได้ไหม ฉันเชื่อว่าจะมีคนสนใจโซลูชันที่สมบูรณ์ของคุณมากพอ
Marek

@Marek เพิ่งสังเกตเห็นความคิดเห็นของคุณ ฉันมีตัวแทนไม่เพียงพอที่จะแก้ไขคำตอบดังนั้นฉันจึงโพสต์ของตัวเอง ขอบคุณ. stackoverflow.com/questions/778678/…
Matt Blaine

3
ฉันรู้ว่ามันเก่าแล้ว และฉันรู้ว่านี่คือ nit (เพราะค่าต่ำสุดเกือบตลอดเวลาเป็นศูนย์); แต่ค่ามาตราส่วนความกว้างควรเป็น(((double) Value - (double) Minimum) / ((double) Maximum - (double) Minimum))เพื่อแก้ไขทางทวารหนัก :)
Jesse Chisholm

122

ตกลงฉันใช้เวลาสักพักในการอ่านคำตอบและลิงก์ทั้งหมด นี่คือสิ่งที่ฉันได้รับจากพวกเขา:

ตัวอย่างผลลัพธ์

คำตอบที่ได้รับการยอมรับจะปิดใช้งานรูปแบบภาพซึ่งจะช่วยให้คุณสามารถกำหนดสีเป็นอะไรก็ได้ที่คุณต้องการ แต่ผลลัพธ์ดูธรรมดา

ป้อนคำอธิบายภาพที่นี่

ใช้วิธีต่อไปนี้คุณจะได้รับสิ่งนี้แทน:

ป้อนคำอธิบายภาพที่นี่

ทำอย่างไร

ขั้นแรกให้รวมสิ่งนี้หากคุณไม่ได้: 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 = normal (สีเขียว); 2 = ข้อผิดพลาด (สีแดง); 3 = คำเตือน (สีเหลือง)

หวังว่าจะช่วยได้!


18
คุณสร้างวิธีการขยายดังนั้นการโทรควรเป็น progressBar1.SetState (2); นอกจากนั้นคำตอบที่ดี!
Edgar Hernandez

5
ควรสังเกตว่าสิ่งนี้พร้อมใช้งานบน Vista + เท่านั้น คุณสามารถดูเอกสารเต็มรูปแบบโดยการค้นหาPBM_SETSTATE
Djof

สวย! ขอบคุณ
sapbucket

1
นี้เป็นที่น่าตื่นตาตื่นใจ แต่จะแบ่งแถบความคืบหน้าของฉันบางส่วนก็จะไม่เติม 100% ....
Norbert Boros

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

37

นี่คือโค้ดที่ได้รับการยอมรับมากที่สุดในเวอร์ชันที่ไม่มีการสั่นไหวซึ่งคุณสามารถหาคำตอบสำหรับคำถามนี้ได้ เครดิตทั้งหมดสำหรับผู้โพสต์คำตอบที่เหนื่อยล้าเหล่านั้น ขอบคุณ Dusty, Chris, Matt และ Josh!

เช่นเดียวกับคำขอของ "Fueled" ในหนึ่งในความคิดเห็นฉันยังต้องการเวอร์ชันที่มีพฤติกรรมมากกว่านี้ ... เป็นมืออาชีพ รหัสนี้จะคงรูปแบบไว้ในโค้ดก่อนหน้า แต่จะเพิ่มการแสดงภาพนอกจอและการบัฟเฟอร์กราฟิก (และกำจัดออบเจ็กต์กราฟิกอย่างเหมาะสม)

ผลลัพธ์: สิ่งที่ดีทั้งหมดและไม่มีการสั่นไหว :)

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

นี่คือสิ่งที่ใกล้เคียงที่สุดกับการใช้งานดั้งเดิมจาก Microsoft
Yakup Ünyılmaz

1
การมีบล็อกการใช้งานและการเรียก Dispose นั้นค่อนข้างซ้ำซ้อน คำตอบที่ดีแม้ว่า
Kevin Stricker

1
ฉันรู้ว่ามันเก่าแล้ว และฉันรู้ว่านี่คือ nit (เพราะค่าต่ำสุดเกือบตลอดเวลาเป็นศูนย์); แต่ค่ามาตราส่วนความกว้างควรเป็น(((double) Value - (double) Minimum) / ((double) Maximum - (double) Minimum))เพื่อแก้ไขทางทวารหนัก :)
Jesse Chisholm

เมื่อฉันใช้ TextRenderer.DrawText () เพื่อวาดข้อความลงใน offscreenimage ผลลัพธ์สุดท้ายบนหน้าจอจะดูเป็นพิกเซลและไม่เหมือนกับป้ายกำกับที่ใช้แบบอักษรเดียวกัน การวาดทั้งหมดนี้โดยตรงไปยัง e.Graphics โดยไม่มี offscreenimager จะให้ผลลัพธ์ที่ถูกต้องแม้ว่า ... ความคิดใด ๆ ทำไม?
CuriousGeorge

1
ใช่ฉันลองไม่ปรับขนาดแล้ว ในที่สุดผมก็เปลี่ยนไป WPF ดังนั้นทุกอย่างที่ฉันจำเป็นต้องถูกสร้างขึ้นเพียงแค่ใน.
CuriousGeorge

28

ในตัวออกแบบคุณเพียงแค่ตั้งค่าคุณสมบัติ ForeColor เป็นสีใดก็ได้ที่คุณต้องการ ในกรณีของสีแดงจะมีสีที่กำหนดไว้ล่วงหน้า

หากต้องการทำในรหัส (C #) ให้ทำสิ่งนี้:

pgs.ForeColor = Color.Red;

แก้ไข : ใช่แล้วยังตั้งค่ารูปแบบเป็นแบบต่อเนื่อง ในรหัสเช่นนี้:

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

การแก้ไขอื่น:คุณจะต้องลบบรรทัดที่อ่านApplication.EnableVisualStyles()จากProgram.cs(หรือคล้ายกัน) ของคุณด้วย หากคุณไม่สามารถทำได้เนื่องจากต้องการให้แอปพลิเคชันที่เหลือมีลักษณะภาพฉันขอแนะนำให้วาดภาพการควบคุมด้วยตัวคุณเองหรือย้ายไปยัง WPF เนื่องจากสิ่งนี้ทำได้ง่ายด้วย WPF คุณสามารถดูบทแนะนำเกี่ยวกับเจ้าของการวาดแถบความคืบหน้าบน codeplex


3
Forecolor = สีแดง; Backcolor = สีน้ำเงิน; สไตล์ = ต่อเนื่อง ไม่มีอะไรเปลี่ยนแปลงมันอยู่อย่างที่ฉันไม่เคยสัมผัส
Ivan Prodanov

3
ขะ ... โอเคฉันเห็นปัญหาแล้ว คุณต้องปิดการใช้งานสไตล์ภาพเพื่อให้สามารถทำงานกับคุณสมบัติได้ อาจเป็นการวาดภาพโดยใช้ธีมที่คุณเลือกไว้ ใน Program.cs มีบรรทัดที่อ่านว่า Application.EnableVisualStyles () ลบบรรทัดนั้นและจะได้ผล มิฉะนั้นคุณจะต้องทาสีตัวควบคุมด้วยตัวเอง อีกทางเลือกหนึ่งคือใช้ WPF (ถ้าเป็นไปได้) เนื่องจากมันช่วยให้คุณทำสิ่งนี้ได้อย่างง่ายดาย
dustyburwell

โปรดให้ข้อมูลเพิ่มเติมเกี่ยวกับ "วิธีการทาสีด้วยตัวเอง"
Ivan Prodanov

1
นี่คือบทแนะนำเกี่ยวกับเจ้าของการวาดแถบความคืบหน้า กระบวนการนี้ซับซ้อนเกินไปสำหรับความคิดเห็น codeproject.com/KB/cpp/VistaProgressBar.aspx
dustyburwell

1
มันเป็นแอปพลิเคชั่นที่น่าเสียดาย EnableVisualStyles () เป็นส่วนสำคัญของโซลูชันนี้ น่าเสียดายที่สิ่งนี้ทำลายสไตล์อื่น ๆ ทั้งหมด
mr.user1065741

16

การใช้คำตอบของ Matt Blaine และ Chris Persichetti ฉันได้สร้างแถบความคืบหน้าซึ่งดูดีขึ้นเล็กน้อยในขณะที่ให้ตัวเลือกสีที่ไม่มีที่สิ้นสุด (โดยทั่วไปฉันเปลี่ยนหนึ่งบรรทัดในโซลูชันของ 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);
        }
    }
}

การใช้งาน:

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#


2
ฉันรู้ว่ามันเก่าแล้ว และฉันรู้ว่านี่คือ nit (เพราะค่าต่ำสุดเกือบตลอดเวลาเป็นศูนย์); แต่ค่ามาตราส่วนความกว้างควรเป็น(((double) Value - (double) Minimum) / ((double) Maximum - (double) Minimum))เพื่อแก้ไขทางทวารหนัก :)
Jesse Chisholm

อัปเดตคำตอบพร้อมข้อเสนอแนะของคุณ
Josh M.

ฉันรู้ว่ามันเก่า แต่ - โค้ดนี้จะเกิดข้อผิดพลาดเมื่อมีค่าเท่ากับ 4 เนื่องจากการLinearGradientBrushอ่านความกว้าง rec เป็น 0 การแก้ไขที่ง่ายที่สุดคืออย่าทำ "padding" ที่ 4px ในโค้ดและวางไว้ในโค้ดแทน แผงหรือบางสิ่งที่มีช่องว่างภายใน (ถ้าคุณต้องการเส้นขอบ) และสร้างrec.Width = (int)((rec.Width * scaleFactor) - 4)เป็นrec.Width = (int)(rec.Width * scaleFactor) + 1
MiDri

14

Modificaton กับคำตอบของ 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);
    }
}

วิธีนี้ใช้งานได้ดีสำหรับการเปลี่ยนสีพื้นหน้า แต่จะกะพริบมากในขณะที่ตัวควบคุม ProgressBar เริ่มต้นไม่ได้ มีความคิดอย่างไรที่จะแก้ปัญหานี้?
เติมน้ำมัน

4
ฉันได้ค้นพบวิธีแก้ปัญหาการกะพริบแล้ว: เพิ่มการบัฟเฟอร์สองครั้งให้กับ ControlStyles ของ ProgressBar ที่ผู้ใช้กำหนดเช่นนี้ SetStyle (ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, ... )
เติมน้ำมัน

ฉันรู้ว่ามันเก่าแล้ว และฉันรู้ว่านี่คือ nit (เพราะค่าต่ำสุดเกือบตลอดเวลาเป็นศูนย์); แต่ค่ามาตราส่วนความกว้างควรเป็น(((double) Value - (double) Minimum) / ((double) Maximum - (double) Minimum))เพื่อแก้ไขทางทวารหนัก :)
Jesse Chisholm

5

ฉันแค่ใส่มันลงในคลาสคงที่

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

หวังว่ามันจะช่วย

มาร์ค


+1: ฉันคิดว่านี่คือสิ่งที่คนส่วนใหญ่หมายถึงสีแดง ทำให้แสดงสถานะข้อผิดพลาด
quantum

3

โดยปกติแถบความคืบหน้าจะเป็นแบบตามธีมหรือตามความต้องการสีของผู้ใช้ ดังนั้นสำหรับการเปลี่ยนสีคุณต้องปิดลักษณะภาพและตั้งค่าForeColorหรือวาดการควบคุมด้วยตัวเอง

สำหรับรูปแบบต่อเนื่องแทนการบล็อกคุณสามารถตั้งค่าStyleคุณสมบัติ:

pBar.Style = ProgressBarStyle.Continuous;

2

แก้ไข

ด้วยเสียงของสิ่งต่าง ๆ ที่คุณกำลังใช้ธีม XP ซึ่งมีแถบสีเขียวที่ใช้ prog-bar ลองพลิก UI Style เป็น Windows Classic แล้วทดสอบอีกครั้ง แต่คุณอาจต้องใช้เหตุการณ์ OnPaint ของคุณเองเพื่อให้ทำสิ่งที่คุณต้องการใน UI Styles ทั้งหมด

หรือตามที่คนอื่นชี้ให้ปิดการใช้งาน VisualStyles สำหรับแอปพลิเคชันของคุณ

ต้นฉบับ

เท่าที่ฉันรู้การเรนเดอร์ของแถบความคืบหน้าเกิดขึ้นในแนวเดียวกับสไตล์ธีมของ windows ที่คุณเลือก (win2K, xp, vista)

คุณสามารถเปลี่ยนสีได้โดยการตั้งค่าคุณสมบัติ

ProgressBar.ForeColor

ฉันไม่แน่ใจว่าคุณจะทำอะไรได้มากกว่านี้ ...

googling บ้าง

มีบทความที่นี่จาก MS KB เกี่ยวกับการสร้างแถบความคืบหน้า "เรียบ"

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


@ Eion, Forecolor = สีแดง; Backcolor = สีน้ำเงิน; สไตล์ = ต่อเนื่อง ไม่มีอะไรเปลี่ยนแปลงมันอยู่อย่างที่ฉันไม่เคยสัมผัสมัน
Ivan Prodanov


2

วิธีการทั้งหมดเหล่านี้ล้มเหลวในการทำงานสำหรับฉัน แต่วิธีนี้ช่วยให้คุณสามารถเปลี่ยนเป็นสตริงสีได้

โปรดทราบว่าฉันพบรหัสนี้จากที่อื่นใน StackOverflow และเปลี่ยนแปลงเล็กน้อย ฉันลืมไปแล้วว่าฉันพบรหัสนี้ที่ไหนและฉันไม่สามารถเชื่อมโยงได้เพราะเหตุนี้จึงต้องขออภัยด้วย

แต่อย่างไรก็ตามฉันหวังว่ารหัสนี้จะช่วยให้ใครบางคนช่วยฉันได้จริงๆ

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

โดยที่ชื่อ "ProgressBar" ถูกใช้แทนที่ด้วยชื่อแถบความคืบหน้าของคุณเอง คุณยังสามารถทริกเกอร์เหตุการณ์นี้ด้วยอาร์กิวเมนต์อื่น ๆ เพียงแค่ตรวจสอบให้แน่ใจว่าอยู่ในวงเล็บ


ทำได้ดีมาก.. ฉันใช้ในงาน ProgressChanged เพื่อเปลี่ยนจากสว่างเป็นมืด ... + 1
BENN1TH

2

เปลี่ยนColorและValue(เปลี่ยนทันที)

ใส่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
    }

}

2
เราต้องพลิกpBar.Value = pBar.Maximum;และSendMessage(pBar.Handle, 1040, (IntPtr)(int)Color.Green, IntPtr.Zero);ด้านในของสภาพร่างกายเพื่อความคืบหน้าในการแสดงสีใหม่ที่ถูกต้อง
DomTheDeveloper

1

ในกรณีที่มีใครมองหาตัวเลือกอื่น .... คุณสามารถขยายแผงใช้เป็นพื้นหลัง (สีขาวหรืออะไรก็ได้) เพิ่มอีกแผงหนึ่งภายในสำหรับพื้นหน้า (แถบเลื่อน) จากนั้นคุณจะมีการควบคุมทั้งหมดในการเปลี่ยนสี ฯลฯ


1

เพียงคลิกขวาที่โครงการของคุณใน Visual Basic Solution Explorer (ที่ไฟล์ vb ของคุณอยู่) และเลือกคุณสมบัติจากเมนู ในหน้าต่างที่ปรากฏขึ้นให้ยกเลิกการเลือก "เปิดใช้งาน XP Visual Styles" และตอนนี้เมื่อคุณตั้งค่า forecolor ก็ควรใช้งานได้แล้ว


0

Јοеу: ข้อความอ้างอิง: โดยปกติแถบความคืบหน้าจะเป็นแนวหรือตามความชอบสีของผู้ใช้ ดังนั้นสำหรับการเปลี่ยนสีคุณต้องปิดลักษณะภาพและตั้งค่าForeColorหรือวาดการควบคุมด้วยตัวเอง

สำหรับรูปแบบต่อเนื่องแทนการบล็อกคุณสามารถตั้งค่าStyleคุณสมบัติ:

pBar.Style = ProgressBarStyle.Continuous;

ProgressBarStyle. ต่อเนื่องกับบล็อกไม่มีประโยชน์เมื่อเปิดใช้งาน VistualStyles ...

บล็อกจะใช้ได้เฉพาะกับสไตล์ภาพที่ปิดใช้งาน ... ซึ่งทำให้ทั้งหมดนี้เป็นจุดที่สงสัย (เกี่ยวกับสีความคืบหน้าแบบกำหนดเอง) เมื่อปิดใช้งานรูปแบบการมองเห็น ... แถบความคืบหน้าควรเป็นสีตามสีหน้า

ฉันใช้คำตอบของวิลเลียมแดเนียลผสมกัน (ด้วยการเปิดใช้งานรูปแบบภาพดังนั้น ForeColor จะไม่แบนราบไม่มีสไตล์) และคำตอบของ Barry (เป็นข้อความที่กำหนดเองบนแถบความคืบหน้า) จาก: ฉันจะใส่ข้อความบน ProgressBar ได้อย่างไร?


0

Vertical Bar UP สำหรับ Down สีแดง:

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

    } 
}

คุณช่วยอธิบายเป็นข้อความหรือแสดงความคิดเห็นเกี่ยวกับโค้ดได้ไหมว่าวิธีนี้แก้ปัญหาได้อย่างไร
Harrison

ฉันรู้ว่านี่คือ nit (เพราะค่าต่ำสุดเกือบตลอดเวลาเป็นศูนย์); แต่ค่ามาตราส่วนความสูงควรเป็น(((double) Value - (double) Minimum) / ((double) Maximum - (double) Minimum))เพื่อแก้ไขทางทวารหนัก :)
Jesse Chisholm

0

แถบความคืบหน้าสี VB.Net ซึ่งสอดคล้องกับคำตอบ WXP Visual Styles คือ ...

ฉันเริ่มต้นด้วยคำตอบจาก 'user1032613' ในวันที่ 17 มีนาคม 2555 โปรดทราบว่าตอนนี้เป็นโมดูลไม่ใช่คลาส จากนั้นฉันก็แปลงรหัส แต่ต้องการมากกว่านั้น โดยเฉพาะอย่างยิ่งโค้ดที่แปลงแล้วแสดงฟังก์ชัน DirectCast เพื่อแปลงจำนวนเต็ม 'สถานะ' เป็นประเภท IntPtr ซึ่งไม่ได้ผล

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

และอีกครั้งเพียงแค่เรียกสิ่งนี้ในรหัสโดยใช้บรรทัดนี้:

Call ModifyProgressBarColor.SetState(prb, 2)

BTW - ฉันลองใช้สีอื่น - 0, 4, 5 - ทั้งหมดแสดงเป็นสีเขียว


0

ฉันรู้ว่ามันเก่าเกินไปที่จะตอบในตอนนี้ .. แต่ถึงกระนั้นก็ยังมีการปรับเปลี่ยนคำตอบของ@ Danielเล็กน้อยสำหรับการแก้ไขปัญหาของการไม่แสดงแถบความคืบหน้าที่มีค่าเป็นศูนย์ เพียงแค่วาดความคืบหน้าก็ต่อเมื่อพบว่าความกว้างของสี่เหลี่ยมด้านในไม่เป็นศูนย์

ขอบคุณผู้ร่วมให้ข้อมูลทั้งหมด

        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

ฉันพบว่าสิ่งนี้สามารถทำได้โดยการวาดรูปสี่เหลี่ยมผืนผ้าภายในแถบความคืบหน้าและกำหนดความกว้างตามค่าปัจจุบันของความคืบหน้า ฉันยังเพิ่มการสนับสนุนสำหรับความคืบหน้าจากขวาไปซ้าย ด้วยวิธีนี้คุณไม่จำเป็นต้องใช้ Image และเนื่องจาก Rectnalge Inflate ไม่ได้เรียกว่าสี่เหลี่ยมผืนผ้าที่วาดนั้นมีขนาดเล็กกว่า

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

ฉันคิดว่าวิธีแก้ปัญหาที่ง่ายที่สุดมันเป็นเพียงการแก้ไขอย่างรวดเร็ว แต่คุณสามารถลบแสดงความคิดเห็น Application.EnableVisualStyles () จาก Program.cs หรืออย่างไรก็ตามคุณตั้งชื่อส่วนที่มีฟังก์ชันหลัก หลังจากนั้นคุณสามารถเปลี่ยนสีจากแถบความคืบหน้าได้อย่างอิสระโดย progressBar.ForeColor = Color.TheColorYouDesire;

static void Main()
        {
            //Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
         }

-5

แก้ไข: ในสอง minuites ทำให้ฉันต้องยิง vs และตรวจสอบไวยากรณ์ที่ฉันพ่ายแพ้ด้วยการตอบสนองที่ดีกว่ามาก ฉันชอบไซต์นี้

        progressBar1 = new ProgressBar();
        progressBar1.ForeColor = Color.Red;

2
ไม่ทำงานตอนนี้ยังว่างอยู่ฉันเพิ่ม progressBar1.value = 50 แต่ยังว่าง
Ivan Prodanov

ลองตั้งค่า maxiumum? progressBar1 = ProgressBar ใหม่ (); progressBar1.ForeColor = Color.Red; progressBar1.Maximum = 100;
Fusspawn

2
ไม่ปัญหาอยู่ในธีม windows ของฉัน
Ivan Prodanov

ไม่รู้ว่าจะได้ผลหรือไม่ แต่ลองแสดงความคิดเห็น Application.EnableVisualThemes (); ที่อยู่ในไฟล์ที่สร้างไว้ล่วงหน้าและสร้าง (ฉันจำไม่ได้ว่าเป็นไฟล์อะไร)
Fusspawn

1
Application.EnableVisualStyles () ขออภัยไม่ใช่ธีม
Fusspawn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.