첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

■ Image 클래스를 사용해 움직이는 GIF 이미지를 만드는 방법을 보여준다.

TestProject.zip
0.01MB

▶ GIFImage.cs

using System;
using System.Windows.Media.Imaging;
using System.Windows;
using System.Windows.Controls;

namespace TestProject;

/// <summary>
/// GIF 이미지
/// </summary>
public class GIFImage : Image
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Field
    ////////////////////////////////////////////////////////////////////////////////////////// Private

    #region Field

    /// <summary>
    /// 디코더
    /// </summary>
    private BitmapDecoder decoder = null;

    /// <summary>
    /// 타이머
    /// </summary>
    private System.Timers.Timer timer = new System.Timers.Timer();

    /// <summary>
    /// 타이머 잠금
    /// </summary>
    private object timerLock = new object();

    /// <summary>
    /// 프레임 카운트
    /// </summary>
    private int frameCount = 0;

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Property
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region 타이머 주기 - Interval

    /// <summary>
    /// 타이머 주기
    /// </summary>
    public double Interval
    {
        get
        {
            return this.timer.Interval;
        }
        set
        {
            this.timer.Interval = value;
        }
    }

    #endregion
    #region 재생 여부 - IsPlaying

    /// <summary>
    /// 재생 여부
    /// </summary>
    public bool IsPlaying { get; private set; }

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region 생성자 - GIFImage()

    /// <summary>
    /// 생성자
    /// </summary>
    public GIFImage() : base()
    {
        IsPlaying = false;

        Interval = 100;

        this.timer.Elapsed += timer_Elapsed;
    }

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Method
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region 시작하기 - Start()

    /// <summary>
    /// 시작하기
    /// </summary>
    public void Start()
    {
        lock(this.timerLock)
        {
            if(this.decoder != null && this.decoder.Frames.Count > 1)
            {
                if(IsPlaying == false)
                {
                    IsPlaying = true;

                    this.timer.Start();
                }
            }
        }
    }

    #endregion
    #region 중단하기 - Stop()

    /// <summary>
    /// 중단하기
    /// </summary>
    public void Stop()
    {
        lock(this.timerLock)
        {
            IsPlaying = false;

            this.timer.Stop();
        }
    }

    #endregion

    ////////////////////////////////////////////////////////////////////////////////////////// Protected

    #region 속성 변경시 처리하기 - OnPropertyChanged(e)

    /// <summary>
    /// 속성 변경시 처리하기
    /// </summary>
    /// <param name="e">이벤트 인자</param>
    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        if(e.Property.Name == "Source")
        {
            if(e.NewValue != null && (e.OldValue == null || (e.NewValue.ToString() != e.OldValue.ToString())))
            {
                Stop();

                try
                {
                    GifBitmapDecoder decoder = new GifBitmapDecoder(new Uri(e.NewValue.ToString()), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);

                    this.decoder = decoder;
                }
                catch
                {
                }

                Start();
            }
        }

        base.OnPropertyChanged(e);
    }

    #endregion

    ////////////////////////////////////////////////////////////////////////////////////////// Private

    #region 타이머 경과시 처리하기 - timer_Elapsed(sender, e)

    /// <summary>
    /// 타이머 경과시 처리하기
    /// </summary>
    /// <param name="sender">이벤트 발생자</param>
    /// <param name="e">이벤트 인자</param>
    private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        Dispatcher.BeginInvoke
        (
            new Action
            (
                delegate
                {
                    this.frameCount = ++this.frameCount % this.decoder.Frames.Count;

                    Source = this.decoder.Frames[this.frameCount];

                    InvalidateArrange();
                }
            ),
            null
        );
    }

    #endregion
}

 

▶ MainWindow.xaml

<Window x:Class="TestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TestProject"
    Width="800"
    Height="600"
    Title="TestProject"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <StackPanel
        HorizontalAlignment="Center"
        VerticalAlignment="Center">
        <local:GIFImage
            HorizontalAlignment="Center"
            SnapsToDevicePixels="True"
            UseLayoutRounding="True"
            RenderOptions.BitmapScalingMode="NearestNeighbor"
            Stretch="None"
            Interval="100"
            Source="pack://application:,,,/IMAGE/elephant.gif" />
    </StackPanel>
</Window>
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요