2015-08-19 9 views
0

У меня проблема с мерцанием в C# WinForms proyect.Мерцание в C# делает SlideButton (DoubleBuffer не работает, видимо)

Я просто сделал контроль SlideButton: это код:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Drawing; 
using System.Data; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Diagnostics; 
using System.ComponentModel.Design; 

namespace DELTA.UI.Search 
{ 
    [Designer("System.Windows.Forms.Design.ParentControlDesigner,System.Design", typeof(IDesigner))] 
    public partial class Slide : UserControl 
    { 
     public Boolean IsShown 
     { 
      get { return button.IsOpen; } 
      set 
      { 
       button.IsOpen = value; 
      } 
     } 

     private int isShownHeight; 

     public Slide() 
     { 
      InitializeComponent(); 
      this.SetStyle(
       System.Windows.Forms.ControlStyles.UserPaint | 
       System.Windows.Forms.ControlStyles.AllPaintingInWmPaint | 
       System.Windows.Forms.ControlStyles.Opaque | 
       System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer, 
       true); 
      this.DoubleBuffered = true; 
      this.ResizeRedraw = true; 
      isShownHeight = this.Height; 
      this.Height = button.Height; 
     } 

     private void boton_MouseEnter(object sender, EventArgs e) 
     { 
      button.BackColor = Color.Gray; 
      button.Cursor = Cursors.Hand; 
     } 

     private void boton_MouseLeave(object sender, EventArgs e) 
     { 
      button.BackColor = Color.White; 
      button.Cursor = Cursors.Arrow; 
     } 

     private void button_OnSlideStateChangedEvent(bool isOpen) 
     { 
      Debug.WriteLine(isOpen); 
      if (!timerSlide.Enabled) 
      { 
       timerSlide.Start(); 
      } 
     } 

     protected override void OnPaint(PaintEventArgs e) 
     { 
      base.OnPaint(e); 

      using (Brush b = new SolidBrush(this.BackColor)) 
       e.Graphics.FillRectangle(b, 0, 0, this.Width, this.Height); 

      int rectWidth = this.Width/10; 
      e.Graphics.FillRectangle(Brushes.LightGray, this.Width/2 - rectWidth/2, this.Height - 3, rectWidth, 3); 
     } 

     private void timerSlide_Tick(object sender, EventArgs e) 
     { 
      if (IsShown && this.Height + button.Height < isShownHeight) 
      { 
       int crecimiento = (isShownHeight - button.Height)/35; 
       this.Height += this.Height + crecimiento >= isShownHeight ? isShownHeight - this.Height : crecimiento; 
      } 
      else if (!IsShown && this.Height > button.Height) 
      { 
       int decrecimiento = (isShownHeight - button.Height)/35; 
       this.Height -= this.Height - decrecimiento <= button.Height ? this.Height - button.Height : decrecimiento; 
      } 
      else 
      { 
       timerSlide.Stop(); 
      } 
     } 

     private void Slide_Resize(object sender, EventArgs e) 
     { 
      //this.Invalidate(new Rectangle(0, this.Height - 12, this.Width, 12)); 
     } 
    } 
} 

Как вы можете видеть, только операция краски я сделать это краска небольшой rectagle в нижней части элемента управления. Элементы управления просто содержат пользовательский buttom с флагом isOpen, который изменяется при нажатии и запускает событие OnSlideStateChangedEvent. Код кнопки:

using DELTA.Util; 
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Diagnostics; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace DELTA.UI.Search 
{ 
    class SlideButton : Button 
    { 
     private Boolean isOpen = true; 
     public Boolean IsOpen 
     { 
      get { return isOpen; } 
      set 
      { 
       isOpen = value; 

       /* Refresh the button with the new appearence */ 
       this.Refresh(); 

       /* Call the event */ 
       if (OnSlideStateChangedEvent != null) 
        OnSlideStateChangedEvent(isOpen); 
      } 
     } 

     public SlideButton() 
      : base() 
     { 
      this.BackColor = Color.White; 
      if (!DesignMode) 
       IsOpen = false; 

      this.DoubleBuffered = true; 
     } 

     /// <summary> 
     /// Event for the Slide 
     /// </summary> 
     [Category("ClickCustomEvents")] 
     [Description("Fired when this is clicked")] 
     public event OnSlideStateChanged OnSlideStateChangedEvent; 
     /// <summary> 
     /// Delegate for the Change of state 
     /// </summary> 
     /// <param name="isOpen"></param> 
     public delegate void OnSlideStateChanged(Boolean isOpen); 

     /// <summary> 
     /// Override to avoid the default OnClick 
     /// </summary> 
     /// <param name="e"></param> 
     protected override void OnClick(EventArgs e) 
     { 
      IsOpen = !isOpen; 
     } 

     protected override void OnPaint(PaintEventArgs e) 
     { 
      // TODO Use the isOpen value to paint it with a filled rectagle or 2 borders 

      /* SETTINGS -> for open/close states of the button */ 
      Color topColor = Color.LightGray; 
      Color otherSidesColor = Color.LightGray; 
      Color backgroud = Color.LightGray; 
      SingletonImages arrow = SingletonImages.ARROW_DOWN; 
      Rectangle arrowPosition = new Rectangle(this.Width - 30, this.Height - 26, 20, 20); 

      if (isOpen) 
      { 
       topColor = Color.LightGray; 
       otherSidesColor = Color.Transparent; 
       backgroud = Color.White; 
       arrow = SingletonImages.ARROW_UP; 
      } 

      /* PAINT ZONE */ 
      /* Background */ 
      using (SolidBrush brush = new SolidBrush(backgroud)) 
       e.Graphics.FillRectangle(brush, new Rectangle(0, 0, this.Width, this.Height)); 

      /* Border */ 
      ControlPaint.DrawBorder(e.Graphics, this.ClientRectangle, 
      otherSidesColor, 2, ButtonBorderStyle.Solid, 
      topColor, 2, ButtonBorderStyle.Solid, 
      otherSidesColor, 2, ButtonBorderStyle.Solid, 
      otherSidesColor, 2, ButtonBorderStyle.Solid); 

      /* Text -> Padding = 5 (This can be changed to use the padding property of the control if need) */ 
      e.Graphics.DrawString(this.Text, this.Font, Brushes.Black, new Point(10, 8)); 

      /* Arrow */ 
      e.Graphics.DrawImage(arrow.Image, arrowPosition); 
     } 
    } 
} 

SingletonImages просто «перечисление» держать изображения для того, чтобы иметь только один экземпляр.

Я изменил свойство DoubleBuffered класса SlideButton на true, но это было ненужным, потому что SlideButton не flickr. Тот, который мерцает, является классом слайдов. Если вам нужна дополнительная информация, спросите, что вы хотите. Любой отзыв?

+0

_I добавил свойство DoubleBuffered к кнопке, но кнопка не мерцает раньше ._ ??? – TaW

+0

Я имел в виду, что я изменил свойство DoubleBuffered класса SlideButton на true, но это было ненужным, потому что SlideButton не flickr. Тот, который мерцает, является классом слайдов. Ред. –

ответ

1

Однажды я столкнулся с этой проблемой. Самый простой (возможно, не самое элегантное) решение было удалить OnPaintBackground() и добавить его в нормальный OnPaint() метод, потому что в противном случае фон окрашен на ваш последний Gfx каждый раз, когда элемент управления недействительным, что вызывает мерцание:

public ctor() 
    { 
     // this does just work with OptimizedDoubleBuffer set to true 
     this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 
    } 

    protected override void OnPaintBackground(PaintEventArgs e) 
    { 
     // do NOT paint the background here but in OnPaint() to prevent flickering! 
     //base.OnPaintBackground(e); 
    } 

    protected override void OnPaint(PaintEventArgs e) 
    { 
     // do the background and the base stuff first (if required) 
     base.OnPaintBackground(e); 
     base.OnPaint(e); 

     // ... custom paint code goes here ... 
    } 

Вы можете попробовать, удачи.

 Смежные вопросы

  • Нет связанных вопросов^_^