у меня возникла проблема с мерцанием в проекте С# WinForms.
Я просто сделал элемент управления 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));
}
}
}
Как видите, единственная операция рисования, которую я делаю, — это рисование маленького прямоугольника в нижней части элемента управления. Элементы управления просто содержат пользовательскую кнопку с флагом 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 не мерцал. Тот, который мерцает, — это класс Slide. Если вам нужна дополнительная информация, спросите, что вы хотите. Любой совет?