2013-12-14 119 views
1

在一個Winforms中,我想改變ToolStripProgressBar的背景顏色,而不是爲整個應用程序取消XP Visual Syles,這可能嗎?也許只禁用StatusStrip控件的XP視覺樣式?我知道一個ToolStripProgressBar不會繼承自控件類型,但是一個StatusStrip確實(不是?),那麼肯定它必須是一個解決方案,或者可能繼承StatusStrip來控制繪製事件或其他東西。我不知道該怎麼做。更改ToolStripProgressBar的顏色而不禁用XP視覺樣式?

我試着將我的StatusStrip控件的RenderMode屬性設置爲專業模式,但系統仍然爲myToolStripProgressBar選擇背景色。

+0

因爲在應用程序級別啓用了VisualStyles('Application.EnableVisualStyles'),所以您可能會運氣不好。 'Forms'有一個'VisualStyles'命名空間,並且進度條從那裏繼承,但是那個名字空間更適合應用那些VisualStyles。 – Plutonix

+0

我敢肯定,沒有你自己做所有的繪畫,這是無法完成的。 –

回答

3

您可以自定義名爲ToolStripProgressBarToolStripControlHost承載的ProgressBar的外觀和風格。您可以通過ToolStripProgressBar的屬性ProgressBar訪問託管的ProgressBar。然後您可以爲該ProgressBar添加Paint事件處理程序。但是,只有當控制樣式UserPaint設置爲ProgressBar時,纔會觸發此Paint事件,這是通過設計(當然與默認支持Paint事件的其他常規控件不同)。所以你可以嘗試下面的代碼。事實上,我試着註釋掉行Application.EnableVisualStyles();看你要與非XP風格ToolStripProgressBar究竟和看起來太簡單了,下面的代碼應該做你想要什麼:

//define some variables first, note that don't rely on the 
//ProgressBarRenderer.ChunkThickness and ProgressBarRenderer.ChunkSpaceThickness 
//because they are actually small and using our own variables will allow us to change 
//the chunk size easily. 
int chunkThickness = 13; 
int chunkSpace = 1; 
Rectangle chunkRect = new Rectangle(0, 0, chunkThickness, 
          toolStripProgressBar1.ProgressBar.Height-4); 
//The hosted ProgressBar's Paint event handler 
private void progressBar_Paint(object sender, PaintEventArgs e){ 
    chunkRect.Location = Point.Empty; 
    chunkRect.Offset(2, 2);     
    var percent = (float) toolStripProgressBar1.Value/toolStripProgressBar1.Maximum; 
    var valueLength = percent * toolStripProgressBar1.ProgressBar.Width; 
    var chunks = (int) (valueLength/(chunkThickness + chunkSpace) + 0.5f); 
    for (int i = 0; i < chunks; i++) { 
    //I use the green color for the chunk color, it's up to you. 
    e.Graphics.FillRectangle(Brushes.Green, chunkRect);      
    chunkRect.Offset(chunkThickness + chunkSpace, 0); 
    } 
    ControlPaint.DrawBorder3D(e.Graphics, toolStripProgressBar1.ProgressBar.ClientRectangle, 
          Border3DStyle.SunkenOuter); 
} 
//Now in your form constructor, just add this code to end up everything before 
//trying running the code: 
public Form1(){ 
    InitializeComponent(); 
    //do this to allow the Paint event to be fired and more ... 
    typeof(Control).GetMethod("SetStyle", System.Reflection.BindingFlags.NonPublic | 
             System.Reflection.BindingFlags.Instance) 
        .Invoke(toolStripProgressBar1.ProgressBar, 
          new object[] {ControlStyles.UserPaint | 
             ControlStyles.OptimizedDoubleBuffer, true }); 
    //hook up the progressBar_Paint event handler for the hosted ProgressBar 
    toolStripProgressBar1.ProgressBar.Paint += progressBar_Paint; 
} 

這不是外觀你在等待什麼?:

enter image description here

更新:連續進度條,它比塊樣式要簡單得多,請嘗試以下更新progressBar_Paint

private void progressBar_Paint(object sender, PaintEventArgs e){ 
    var percent = (float) toolStripProgressBar1.Value/toolStripProgressBar1.Maximum; 
    var valueLength = percent * toolStripProgressBar1.ProgressBar.Width; 
    var chunkRect = new RectangleF(2,2,valueLength, 
           toolStripProgressBar1.ProgressBar.Height-4); 
    e.Graphics.FillRectangle(Brushes.Green, chunkRect); 
    ControlPaint.DrawBorder3D(e.Graphics, toolStripProgressBar1.ProgressBar.ClientRectangle, 
          Border3DStyle.SunkenOuter); 
} 
+0

@ElektroStudios它比實現塊式進度條簡單得多,請參閱我的代碼更新。 –

+0

在我看到你的更新之前,我已經解決了它調整塊空間的值,這就是爲什麼我刪除了我的評論,對不起給你更多的工作,這是我的錯,沒有注意到這些變量,謝謝你的時間 – ElektroStudios

+1

+1 By far我找到的最佳解決方案。 –

0

我只是想分享我的基於@ King King C#的vbnet方法。

我試圖修改它的通用使用,但代碼仍然有點硬編碼。

''' <summary> 
''' The Backcolor to fill the ToolStrip ProgressBar. 
''' </summary> 
Private ProgressBar_BackColor As Brush = New SolidBrush(Color.FromArgb(120, 147, 73)) 

''' <summary> 
''' The ForeColor to fill the ToolStrip ProgressBar. 
''' </summary> 
Private ProgressBar_ForeColor As Brush = New SolidBrush(Color.Black) 

''' <summary> 
''' Draws a border effect inside the bounds of the ProgressBar. 
''' </summary> 
Private ProgressBar_Border As Single = 0 

''' <summary> 
''' Indicates the StringFormat of the ProgressBar Text. 
''' </summary> 
Private ProgressBar_Text_Format As StringFormat = 
    New StringFormat With {.Alignment = Drawing.StringAlignment.Center, 
          .Trimming = StringTrimming.EllipsisCharacter} 


Public Sub New() 

    ' Necessary call to the designer. 
    InitializeComponent() 

    ' Set the Style of the ToolStripProgesssBar (For be able to fill the progressbar with a custom color). 
    GetType(Control).GetMethod("SetStyle", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance). 
        Invoke(ToolStripProgressBar1.ProgressBar, 
          New Object() {ControlStyles.UserPaint Or ControlStyles.OptimizedDoubleBuffer, True}) 

End Sub 

' ProgressBarStatus [Paint] 
Private Sub ProgressBarStatus_Paint(sender As Object, e As PaintEventArgs) _ 
Handles ToolStripProgressBar1.Paint 

    ' Fill the progressbar 
    Select Case sender.style 

     Case ProgressBarStyle.Continuous 

      ' The ProgressBar Rectangle. 
      Dim ProgressBarRect As RectangleF = 
       New RectangleF(ProgressBar_Border/2, ProgressBar_Border/2, 
           CSng(sender.Value/sender.Maximum) * CSng(sender.ProgressBar.Width - ProgressBar_Border), 
           sender.ProgressBar.Height - ProgressBar_Border) 

      e.Graphics.FillRectangle(ProgressBar_BackColor, ProgressBarRect) 

     Case ProgressBarStyle.Blocks 

      ' The Width of each block. 
      Dim BlockWidth As Integer = 10 

      ' The space between each block. 
      Dim BlockSpace As Integer = 1 

      ' The ProgressBar Rectangle. 
      Dim ProgressBarRect As Rectangle = 
       New Rectangle(0, 0, BlockWidth, sender.ProgressBar.Height - 4) 

      ' Calculate the block count. 
      Dim PercentDone As Single = CSng(sender.ProgressBar.Value/sender.ProgressBar.Maximum) 
      Dim valueLength As Single = PercentDone * CSng(sender.ProgressBar.Width) 
      Dim BlockCount As Integer = CInt(valueLength/(BlockWidth + BlockSpace) + 0.5F) 

      ProgressBarRect.Offset(2, 2) 

      For i As Integer = 0 To BlockCount - 1 
       e.Graphics.FillRectangle(ProgressBar_BackColor, ProgressBarRect) 
       ProgressBarRect.Offset(BlockWidth + BlockSpace, 0) 
      Next 

      ControlPaint.DrawBorder3D(e.Graphics, sender.ProgressBar.ClientRectangle, Border3DStyle.SunkenOuter) 

    End Select 

    ' Draw the Text 
    Dim TextBounds As Rectangle = sender.ProgressBar.Bounds 
    TextBounds.Inflate(0, 4) ' Correct the Text position. 

    Using fnt As New Font(CType(sender.ProgressBar.Font.FontFamily, FontFamily), 
          CSng(sender.ProgressBar.Font.SizeInPoints) + 1, 
          FontStyle.Bold) 

     e.Graphics.DrawString(sender.ProgressBar.Value, fnt, ProgressBar_ForeColor, TextBounds, ProgressBar_Text_Format) 

    End Using 

End Sub