2011-08-09 2 views
3

Я хотел сделать бар вертикального прогресса, так что я нашел это: Vertical progress barUpsidedown Vertical Progress Bar?

Но теперь, как если у вас есть Horizitonal Progress Bar вы можете заставить его работать с LeftToRight/RightToLeft, поэтому я хочу, чтобы мой Vertical один для работы с UpToDown и а не от DownToUp, как сейчас работает.

Возможно ли это?

Вот мой код

public class VerticalProgressBar : ProgressBar 
{ 
    protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.Style |= 0x04; 
      return cp; 
     } 
    } 
} 

Я использую C# .NET 3.5 Windows Forms

+0

WPF? Silverlight? Winforms? ASP? –

+0

Winforms .... :) – Danpe

+3

Вам нужно нарисовать его самостоятельно, а не использовать стандартный элемент управления. Могу ли я предложить WPF для такого приложения. –

ответ

1

Там, кажется, не будет каких-либо CreateParams, которые поддерживают инвертированные вертикальной ProgressBar. Это параметры стиля из Windows API:

#define PBS_SMOOTH   0x01 
#define PBS_VERTICAL  0x04 
#define PBS_MARQUEE   0x08 
#define PBS_SMOOTHREVERSE 0x10 

#define PBST_NORMAL   1 
#define PBST_ERROR   2 
#define PBST_PAUSED   3 

Я попытался изменить значения RightToLeft безрезультатно. Также не существует способа произвольного поворота элемента управления Windows Forms.

Возможным решением может быть использование WPF ProgressBar. Вы можете вращать его на 90 градусов, и он должен делать то, что вы ищете. Другой вариант - использовать сторонний элемент управления Progressbar или создать персонализированную визуализацию. Должно быть довольно просто сделать простую панель прогресса.

+0

Могу ли я повернуть элемент управления Windows Forms? – Danpe

+0

Нет, вы не можете повернуть сам элемент управления. Однако вы можете переопределить метод Paint() и повернуть содержимое, но в вашем случае это не поможет. Если вы не хотите накладных расходов WPF, вы можете найти множество настраиваемых элементов управления progressbar в [CodeProject] (http: // http: //www.codeproject.com/).Вы можете, по крайней мере, использовать один из них в качестве отправной точки для настраиваемого элемента управления. –

+0

И могу ли я просто добавить библиотеки WPF? или мне нужно создать для него новый проект WPF? Если я могу только добавить библиотеки, вы можете показать мне пример? Я новичок в WPF. – Danpe

1

Вы должны переопределить OnPaint(), как это:

public class VerticalProgressBar : ProgressBar 
{ 
    protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.Style |= 0x04; 
      return cp; 
     } 
    } 

    public VerticalProgressBar() 
    { 
     // Enable OnPaint overriding 
     this.SetStyle(ControlStyles.UserPaint, true); 
    } 

    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
    { 
     Graphics dc = e.Graphics; 

     if (this.Minimum == this.Maximum || (this.Value - Minimum) == 0) 
      return; 

     int width = this.Width;                 // The bar width 
     int height = (this.Value - this.Minimum) * this.Height/(this.Maximum - this.Minimum); // The bar height 
     int x = 2;       // The bottom-left x pos of the bar (or upper left on upsidedown bar) 
     int y = this.Height - 1;   // The bottom-left y pos of the bar (or upper left on upsidedown bar) 

     int blockheight = width * 3/4; // The height of the block 

     if (this.RightToLeftLayout && this.RightToLeft == System.Windows.Forms.RightToLeft.No) 
      for (int currentpos = 0; currentpos < height; currentpos += blockheight + 1) 
       dc.FillRectangle(new SolidBrush(this.ForeColor), x, currentpos, width, blockheight); 
     else 
      for (int currentpos = y; currentpos > y - height; currentpos -= blockheight + 1) 
       dc.FillRectangle(new SolidBrush(this.ForeColor), x, currentpos - blockheight, width, blockheight); 

     base.OnPaint(e); 
    } 
} 

Теперь вы можете использовать его таким же образом, как Vertical progress bar вы связаны между собой и LeftToRight/RightToLeft функциональность будет имитировать один из нормального ProgressBar (относительно прогресса ориентация рисунка).

1

Я заметил, что код выше не работает с визуальными стилями. Вот улучшенная версия вертикальной полосы прогресса, который должен охватывать визуальные стили:

public class VerticalProgressBar : ProgressBar 
{ 
    protected override CreateParams CreateParams 
    { 
     get 
     { 
      // Avoid CA2122 
      new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); 

      CreateParams cp = base.CreateParams; 
      cp.Style |= 0x04; 
      return cp; 
     } 
    } 

    public VerticalProgressBar() 
    { 
     // Enable OnPaint overriding 
     this.SetStyle(ControlStyles.UserPaint, true); 
    } 

    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
    { 
     if (ProgressBarRenderer.IsSupported) 
     { 
      ProgressBarRenderer.DrawVerticalBar(e.Graphics, e.ClipRectangle); 

      const int HORIZ_OFFSET = 3; 
      const int VERT_OFFSET = 2; 

      if (this.Minimum == this.Maximum || (this.Value - Minimum) == 0 || 
        this.Height < 2 * VERT_OFFSET || this.Width < 2 * VERT_OFFSET) 
       return; 

      int barHeight = (this.Value - this.Minimum) * this.Height/(this.Maximum - this.Minimum); 
      barHeight = Math.Min(barHeight, this.Height - 2 * VERT_OFFSET); 
      int barWidth = this.Width - 2 * HORIZ_OFFSET; 

      if (this.RightToLeftLayout && this.RightToLeft == System.Windows.Forms.RightToLeft.No) 
      { 
       ProgressBarRenderer.DrawVerticalChunks(e.Graphics, 
         new Rectangle(HORIZ_OFFSET, VERT_OFFSET, barWidth, barHeight)); 
      } 
      else 
      { 
       int blockHeight = 10; 
       int wholeBarHeight = Convert.ToInt32(barHeight/blockHeight) * blockHeight; 
       int wholeBarY = this.Height - wholeBarHeight - VERT_OFFSET; 
       int restBarHeight = barHeight % blockHeight; 
       int restBarY = this.Height - barHeight - VERT_OFFSET; 
       ProgressBarRenderer.DrawVerticalChunks(e.Graphics, 
        new Rectangle(HORIZ_OFFSET, wholeBarY, barWidth, wholeBarHeight)); 
       ProgressBarRenderer.DrawVerticalChunks(e.Graphics, 
        new Rectangle(HORIZ_OFFSET, restBarY, barWidth, restBarHeight)); 
      } 
     } 

     base.OnPaint(e); 
    } 
} 

мне пришлось рисовать отдельные куски для снизу вверх прогресса бара, потому что я хотел, чтобы выглядеть и чувствовать себя других баров прогресса. В противном случае полоса, казалось бы, была вычерчена из середины.

2

Код, который поддерживает визуальные стили, содержит ошибку. Этот код:

ProgressBarRenderer.DrawVerticalBar(e.Graphics, e.ClipRectangle); 

должен быть заменен с этим одним:

ProgressBarRenderer.DrawVerticalBar(e.Graphics, ClientRectangle); 

И я перепечатывать полный исходный код без этой ошибки:

public class VerticalProgressBar : ProgressBar 
    { 
     protected override CreateParams CreateParams 
     { 
      get 
      { 
       // Avoid CA2122 
       new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); 

       CreateParams cp = base.CreateParams; 
       cp.Style |= 0x04; 
       return cp; 
      } 
     } 

     public VerticalProgressBar() 
     { 
      // Enable OnPaint overriding 
      this.SetStyle(ControlStyles.UserPaint, true); 
     } 

     protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 
     { 
      if (ProgressBarRenderer.IsSupported) 
      { 
       ProgressBarRenderer.DrawVerticalBar(e.Graphics, ClientRectangle); 

       const int HORIZ_OFFSET = 3; 
       const int VERT_OFFSET = 2; 

       if (this.Minimum == this.Maximum || (this.Value - Minimum) == 0 || 
         this.Height < 2 * VERT_OFFSET || this.Width < 2 * VERT_OFFSET) 
        return; 

       int barHeight = (this.Value - this.Minimum) * this.Height/(this.Maximum - this.Minimum); 
       barHeight = Math.Min(barHeight, this.Height - 2 * VERT_OFFSET); 
       int barWidth = this.Width - 2 * HORIZ_OFFSET; 

       if (this.RightToLeftLayout && this.RightToLeft == System.Windows.Forms.RightToLeft.No) 
       { 
        ProgressBarRenderer.DrawVerticalChunks(e.Graphics, 
          new Rectangle(HORIZ_OFFSET, VERT_OFFSET, barWidth, barHeight)); 
       } 
       else 
       { 
        int blockHeight = 10; 
        int wholeBarHeight = Convert.ToInt32(barHeight/blockHeight) * blockHeight; 
        int wholeBarY = this.Height - wholeBarHeight - VERT_OFFSET; 
        int restBarHeight = barHeight % blockHeight; 
        int restBarY = this.Height - barHeight - VERT_OFFSET; 
        ProgressBarRenderer.DrawVerticalChunks(e.Graphics, 
         new Rectangle(HORIZ_OFFSET, wholeBarY, barWidth, wholeBarHeight)); 
        ProgressBarRenderer.DrawVerticalChunks(e.Graphics, 
         new Rectangle(HORIZ_OFFSET, restBarY, barWidth, restBarHeight)); 
       } 
      } 

      base.OnPaint(e); 
     } 
    }