Анимация GIF-изображения вызывает исключение

Я пытаюсь анимировать изображение GIF в XE7, но когда я устанавливаю для свойства Animate значение True, возникает исключение.

введите здесь описание изображения

Вот .pas

unit Unit6;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  GifImg, Vcl.ExtCtrls;

type
  TForm6 = class(TForm)
    Spinner: TImage;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form6: TForm6;

implementation

{$R *.dfm}

procedure TForm6.Button1Click(Sender: TObject);
begin
  TGifImage(Spinner.Picture.Graphic).Animate := True;
end;

end.

И .dfm

object Form6: TForm6
  Left = 0
  Top = 0
  BorderStyle = bsDialog
  Caption = 'GIF Test'
  ClientHeight = 83
  ClientWidth = 115
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poScreenCenter
  PixelsPerInch = 96
  TextHeight = 13
  object Spinner: TImage
    Left = 45
    Top = 13
    Width = 24
    Height = 24
    AutoSize = True
    IncrementalDisplay = True
    ParentShowHint = False
    Picture.Data = {
      0D546478536D617274496D61676547494638396118001800840000FFFFFF0000
      00CECECEFAFAFAE0E0E0B0B0B0E8E8E88E8E8EC8C8C89C9C9CD8D8D8A8A8A8C0
      C0C0F2F2F2767676868686B8B8B8686868000000000000000000000000000000
      00000000000000000000000000000000000000000000000000000021FE1A4372
      6561746564207769746820616A61786C6F61642E696E666F0021FF0B4E455453
      43415045322E30030100000021F90401070000002C00000000180018000008B3
      0001081C48100004080513262440F0C10385100110708050608408031B308C28
      F081838D170712D8C8118283041D1F02D0D8002249001E5B1E1438D2A5430103
      17B4244852E34B010E51725C397267C6050F16701CF932A1D1A150A30A14B020
      4182053887FA24D0A081000856B142EDCAF4A9D4B368053680203622D3850B16
      4030BBB0E8D10524053CD598B1A6DAA75F5BFAE54A902E4D085907131E7A70A7
      80AC129B3A159017324BAD041FA72DD8756840003B}
    ShowHint = True
    Transparent = True
  end
  object Button1: TButton
    Left = 13
    Top = 49
    Width = 91
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
end

У меня установлены элементы управления DevExpress, а свойство Picture в редакторе свойств объявлено как TcxSmartImage. Однако этот класс происходит от TGraphic, поэтому я не понимаю, как это могло вызвать исключение.


person norgepaul    schedule 26.01.2015    source источник
comment
Основываясь на размерах изображения и количестве данных в поле Picture.Data, я думаю, что когда вы добавляли изображение в формате gif во время разработки, оно обрабатывалось как статическое изображение в формате gif, поэтому был добавлен только первый кадр. Также откуда TGifImage получит все необходимые данные о параметрах анимации (количество кадров, порядок кадров, задержки кадров и т.д.). Я серьезно сомневаюсь, что вся необходимая информация может храниться в таком маленьком блоке данных.   -  person SilverWarior    schedule 26.01.2015


Ответы (1)


TGifImage(Spinner.Picture.Graphic).Animate := True;

Вероятным объяснением является то, что Spinner.Picture.Graphic не относится к типу TGifImage. Я подозреваю, что если вы используете приведение с проверкой во время выполнения, вы обнаружите, что это так.

(Spinner.Picture.Graphic as TGifImage).Animate := True;

Если вы расшифруете шестнадцатеричный код, содержащийся в контексте Picture.Data, который вы показали, вы найдете этот текст ASCII:

TdxSmartImage

Это говорит мне о том, что ваш элемент управления изображением не содержит TGifImage.


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

С другой стороны, недопустимый тип при использовании с проверенным приведением во время выполнения приведет к информативному сообщению об ошибке.


Спасибо @SpeedFreak за полезный комментарий, относящийся к этому элементу поддержки DevExpress: https://www.devexpress.com/Support/Center/Question/Details/Q562011

Похоже, что компоненты DevExpress регистрируют собственный обработчик для расширения GIF. И этот обработчик не поддерживает анимацию.

Поэтому я предполагаю, что самый простой способ решить эту проблему - загрузить изображение GIF во время выполнения из ресурса, и это позволит избежать использования всей магии времени разработки, которая связывает расширения изображения с графическими компонентами.

person David Heffernan    schedule 26.01.2015
comment
Ты прав, Дэвид. На самом деле я сначала использовал (Spinner.Picture.Graphic as TGifImage), но получил упомянутую вами ошибку времени выполнения. Думаю, я свяжусь с DevExpress и посмотрю, что они скажут. - person norgepaul; 26.01.2015
comment
Вполне вероятно, что вы найдете там TdxSmartImageGIF89a! - person David Heffernan; 26.01.2015
comment
Да, вы могли бы так подумать, но, насколько я могу судить, TdxSmartImageGIF89a нигде не объявлен в исходниках DevExpress. Я предполагаю, что имя класса генерируется при потоковой передаче данных GIF, но оно никогда не предназначалось для использования фактического типа класса. - person norgepaul; 26.01.2015
comment
Узнать, какой это тип, можно с помощью Spinner.Picture.Graphic.ClassName. В любом случае, я думаю, мы добрались до сути вопроса, который вы задали. - person David Heffernan; 26.01.2015
comment
Спасибо. Я обновлю ответ, когда получу ответ от DevExpress. - person norgepaul; 26.01.2015
comment
Если вы изучите шестнадцатеричные данные, вы заметите, что первый байт равен 0D. Это значение определяет длину следующей строки имени класса. т.е. имя класса TdxSmartImage. Строка GIF89a, следующая за ней, является подписью GIF, которая появляется в начале файла GIF. Значение подписи может быть либо GIF87a, либо GIF89a. Запись использование TdxSmartImage на DevExpress есть несколько отчетов об этой проблеме. Пока их позиция сводится к Слишком плохо. Научитесь с этим жить. /Q562011 - person SpeedFreak; 26.01.2015
comment
@SpeedFreak Большое спасибо. Очень полезная ссылка. Я предполагаю, что самый чистый способ обойти это — загрузить графику во время выполнения и, таким образом, явно контролировать, какой тип TGraphic используется. - person David Heffernan; 26.01.2015