// цикл анимации воспроизводится один раз,
// затем происходит исключение
Bitmap bmp = new Bitmap("Dance.gif");
pictureBox1.Image = bmp;
// цикл анимации воспроизводится один раз,
// затем происходит исключение
Image img = Image.FromFile("Dance.gif");
pictureBox1.Image = img;
// если делать так, то исключение возникает моментально,
// на первом же кадре
pictureBox1.ImageLocation = "Dance.gif";
pictureBox1.Load();
Exception при показе анимации GIF в PictureBox
Цитата:
System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+.
Пробовал так:
Код:
Причём, если пробовать последним способом, то выкидывается окошко с сообщением об исключении в таком виде (рис. 2).
Вопрос: как перехватывать это исключение? Где, в каком месте? Пробовал даже так:
Код:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try
{
Application.Run(new Form1());
}
catch (Exception ex)
{
MessageBox.Show("Test");
}
}
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try
{
Application.Run(new Form1());
}
catch (Exception ex)
{
MessageBox.Show("Test");
}
}
не помогает, исключение не перехватывается.
Как перехватить это исключение, чтобы моя программа не вылетала при показе некорректных джифок?
Гуглил. Похожий вопрос задаётся часто. Ответа не нашёл.
Другой вопрос: почему в PictureBox анимация воспроизводится медленнее, чем в WebBrowser? Из-за этого, вероятно, придётся показывать джифки в компоненте WebBrowser.
Используется VS2005, Framework 2.0.
Вот ссылка на одно из решений.
Хотя вот сейчас в gif animator'е смотрел этот файлик - вроде всё нормально, ничего необычного.
Причём эти глючащие картинки нормально показываются во всех браузерах, в том числе и в компоненте WebBrowser. А просмотрщики картинок воспроизводят цикл анимации лишь один раз, потом она останавливется.
Но самое главное: я не могу перехватить исключение! Такое ощущение, что оно происходит в недрах GDI+.
Цитата: koodeer
Но самое главное: я не могу перехватить исключение! Такое ощущение, что оно происходит в недрах GDI+.
Судя по тому, что у тебя не прорисовываются контролы (прямоугольники), то это натурально падение подсистемы рендеринга. Такие же "конверты" бывают когда директХ падает. Предлагаю поставить сервиспаки и обновления на дотнет и винды.
Что ж, так и сделаю.
самое интересное, что первые два способа работают, а последний - экскепшн. надо бы кое что проверить...
Код:
ImageAnimator.Animate(Image.FromFile("Dance.gif"),
delegate(object o, EventArgs a)
{
pictureBox1.Image = new Bitmap((Bitmap)o);
}
);
delegate(object o, EventArgs a)
{
pictureBox1.Image = new Bitmap((Bitmap)o);
}
);
Цитата:
Другой вопрос: почему в PictureBox анимация воспроизводится медленнее
внутри pictureBox используется как раз ImageAnimator а внутри ImageAnimator.Animate
Код:
...
animationThread = new Thread(new ThreadStart(ImageAnimator.AnimateImages50ms));
animationThread.Name = typeof(ImageAnimator).Name;
animationThread.IsBackground = true;
animationThread.Start();
...
animationThread = new Thread(new ThreadStart(ImageAnimator.AnimateImages50ms));
animationThread.Name = typeof(ImageAnimator).Name;
animationThread.IsBackground = true;
animationThread.Start();
...
Код:
public class ImageInfo
{
private bool animated;
private int frame;
private int frameCount;
private int[] frameDelay;
private bool frameDirty;
private Image image;
private const int PropertyTagFrameDelay = 0x5100;
public bool Animated
{
get
{
return this.animated;
}
}
public int Frame
{
get
{
return this.frame;
}
set
{
if (this.frame != value)
{
if ((value < 0) || (value >= this.FrameCount))
{
throw new ArgumentException("InvalidFrame", "value");
}
if (this.Animated)
{
this.frame = value;
this.frameDirty = true;
}
}
}
}
public int FrameCount
{
get
{
return this.frameCount;
}
}
public bool FrameDirty
{
get
{
return this.frameDirty;
}
}
public Image Image
{
get
{
return this.image;
}
}
public ImageInfo(Image image)
{
this.image = image;
this.animated = ImageAnimator.CanAnimate(image);
if (this.animated)
{
this.frameCount = image.GetFrameCount(FrameDimension.Time);
PropertyItem propertyItem = image.GetPropertyItem(0x5100);
if (propertyItem != null)
{
byte[] buffer = propertyItem.Value;
this.frameDelay = new int[this.FrameCount];
for (int i = 0; i < this.FrameCount; i++)
{
this.frameDelay = ((buffer[i * 4] + (0x100 * buffer[(i * 4) + 1])) + (0x10000 * buffer[(i * 4) + 2])) + (0x1000000 * buffer[(i * 4) + 3]);
}
}
}
else
{
this.frameCount = 1;
}
if (this.frameDelay == null)
{
this.frameDelay = new int[this.FrameCount];
}
}
public int FrameDelay(int frame)
{
return this.frameDelay[frame];
}
public void UpdateFrame()
{
if (this.frameDirty)
{
if (this.image.SelectActiveFrame(FrameDimension.Time, this.Frame) != 0)
throw new System.Runtime.InteropServices.ExternalException();
this.frameDirty = false;
}
}
}
{
private bool animated;
private int frame;
private int frameCount;
private int[] frameDelay;
private bool frameDirty;
private Image image;
private const int PropertyTagFrameDelay = 0x5100;
public bool Animated
{
get
{
return this.animated;
}
}
public int Frame
{
get
{
return this.frame;
}
set
{
if (this.frame != value)
{
if ((value < 0) || (value >= this.FrameCount))
{
throw new ArgumentException("InvalidFrame", "value");
}
if (this.Animated)
{
this.frame = value;
this.frameDirty = true;
}
}
}
}
public int FrameCount
{
get
{
return this.frameCount;
}
}
public bool FrameDirty
{
get
{
return this.frameDirty;
}
}
public Image Image
{
get
{
return this.image;
}
}
public ImageInfo(Image image)
{
this.image = image;
this.animated = ImageAnimator.CanAnimate(image);
if (this.animated)
{
this.frameCount = image.GetFrameCount(FrameDimension.Time);
PropertyItem propertyItem = image.GetPropertyItem(0x5100);
if (propertyItem != null)
{
byte[] buffer = propertyItem.Value;
this.frameDelay = new int[this.FrameCount];
for (int i = 0; i < this.FrameCount; i++)
{
this.frameDelay = ((buffer[i * 4] + (0x100 * buffer[(i * 4) + 1])) + (0x10000 * buffer[(i * 4) + 2])) + (0x1000000 * buffer[(i * 4) + 3]);
}
}
}
else
{
this.frameCount = 1;
}
if (this.frameDelay == null)
{
this.frameDelay = new int[this.FrameCount];
}
}
public int FrameDelay(int frame)
{
return this.frameDelay[frame];
}
public void UpdateFrame()
{
if (this.frameDirty)
{
if (this.image.SelectActiveFrame(FrameDimension.Time, this.Frame) != 0)
throw new System.Runtime.InteropServices.ExternalException();
this.frameDirty = false;
}
}
}
Код:
ImageInfo ii;
private void Form1_Load(object sender, EventArgs e)
{
ii = new ImageInfo(Image.FromFile("Dance.gif"));
if (ii.Animated)
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
ii.Frame = ii.Frame >= ii.FrameCount - 1 ? 0 : ii.Frame + 1;
ii.UpdateFrame();
if (pictureBox1.Image != null)
pictureBox1.Image.Dispose();
pictureBox1.Image = new Bitmap(ii.Image);
}
private void Form1_Load(object sender, EventArgs e)
{
ii = new ImageInfo(Image.FromFile("Dance.gif"));
if (ii.Animated)
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
ii.Frame = ii.Frame >= ii.FrameCount - 1 ? 0 : ii.Frame + 1;
ii.UpdateFrame();
if (pictureBox1.Image != null)
pictureBox1.Image.Dispose();
pictureBox1.Image = new Bitmap(ii.Image);
}
Цитата: bagie2
а такой код тоже вызовет исключение?
Увы, всё то же самое.
Цитата: bagie2
внутри pictureBox используется как раз ImageAnimator а внутри ImageAnimator.Animate
Ага, это интересно. Раньше как-то не задумывался, как это реализовано. Покопаюсь.
Цитата: bagie2
или вообще попробуйте что-нибудь типа
Попробовал. Исключение тоже возникает. Но весьма любопытно: выскакивает окошко с сообщением об ошибке в GDI+, но анимация при этом продолжается.
Но! Это исключение уже удаётся перехватить. При чём, что любопытно, оно происходит сразу же дважды.
Возникает оно в методе UpdateFrame() в строке
Код:
if (this.image.SelectActiveFrame(FrameDimension.Time, this.Frame) != 0)
Лишь после того, как этот компьютер получил свободный доступ к Интернету (раньше не было), и Винда обновилась по максимуму, всё заработало. Стали не нужны никакие ухищрения. Танцор, сцуко, наяривает и не думает вываливаться в эксепшн.
Мораль: обновления рулят!