Проблема с отображением прозрачности GIF в PictureBox
На форме есть много динамически создающихся PictureBox. Все они являются дочерними элементами управления для некоторого Panel. У изображений, которые я желаю отображать, присутствует альфа канал. Проблема в том, что альфа канал интерпретируется неправильно.
Установка свойства BackColor не помогает: PictureBox'ы принадлежат Panel, а значит и задний фон - белая панель.
В интернете нашел сдеюущий способ, но он не работает (изображение не отображается):
public class PictureBoxTW : PictureBox
{
protected override void OnPaintBackground(PaintEventArgs e)
// Paint background with underlying graphics from other controls
{
base.OnPaintBackground(e);
Graphics g = e.Graphics;
if (Parent != null)
{
// Take each control in turn
int index = Parent.Controls.GetChildIndex(this);
for (int i = Parent.Controls.Count - 1; i > index; i--)
{
Control c = Parent.Controls[i];
// Check it's visible and overlaps this control
if (c.Bounds.IntersectsWith(Bounds) && c.Visible)
{
// Load appearance of underlying control and redraw it on this background
Bitmap bmp = new Bitmap(c.Width, c.Height, g);
c.DrawToBitmap(bmp, c.ClientRectangle);
g.TranslateTransform(c.Left - Left, c.Top - Top);
g.DrawImageUnscaled(bmp, Point.Empty);
g.TranslateTransform(Left - c.Left, Top - c.Top);
bmp.Dispose();
}
}
}
}
}
У кого-нибудь найдется готовый способ решения этой проблемы, для которого мне не потребуются танцы с бубном?
Ответы (1 шт):
Косо да ломо решил проблему, но мне пришлось отказаться от любых PictureBox, принять факт двойной буферизации и рисовать прямо на форме. Далее следуют рабочие обрывки из класса реализации.
class TransparentPictureBox {
public bool require_paint { get; private set; }
public Action<Effect> force_paint { get; private set; }
private Bitmap frame;
public TransparentPictureBox (string file, Action<TransparentPictureBox> force_paint) {
this.frame = new Bitmap(file);
this.force_paint = force_paint;
OnShow();
}
/**
* @brief Обрабатывает событие рисования.
* @details
* Отрисовывает текущий кадр эффекта поверх всего остального.
* Вызывающий должен самостоятельно обрабатывать порядок отрисовки
*
* @param e Аргументы события для отрисовки.
*/
public void Paint(PaintEventArgs e) {
require_paint = false;
ImageAnimator.UpdateFrames();
e.Graphics.DrawImage(frame, new Point(0, 0));
}
private void OnFrameChanged(object sender, EventArgs e) {
require_paint = true;
force_paint(this);
}
/// @brief Сохранение состояния перед скрытием.
public void OnHide() {
require_paint = true;
force_paint(this);
ImageAnimator.StopAnimate(frame, new EventHandler(OnFrameChanged));
}
/// @brief Возобновление состояния перед появлением.
public void OnShow() {
ImageAnimator.Animate(frame, new EventHandler(OnFrameChanged));
require_paint = true;
force_paint(this);
}
}
То есть я рисую на форме абсолютно все объекты TransparentPictureBox каждый раз, когда меняется кадр анимации любого из них.
Не думаю, что мне это понравится. Этот способ имеет множество недостатков и требует большого (боль какого) внешнего управления.