আমি কি নিয়ন্ত্রণ টাইপ ব্যবহার করা উচিত - Image
, MediaElement
ইত্যাদি?
আমি কি নিয়ন্ত্রণ টাইপ ব্যবহার করা উচিত - Image
, MediaElement
ইত্যাদি?
উত্তর:
সঠিকভাবে কাজ করার জন্য আমি এই প্রশ্নের সর্বাধিক জনপ্রিয় উত্তর পেতে পারি না (উপরে ডারিও দ্বারা) work ফলাফলটি ছিল অদ্ভুত, অদ্ভুত শৈলীগুলির সাথে চপ্পি অ্যানিমেশন। আমি এখনও অবধি সবচেয়ে ভাল সমাধানটি খুঁজে পেয়েছি: https://github.com/XamlAnimatedGif/WpfAnimatedGif
আপনি এটি নিউগেট দিয়ে ইনস্টল করতে পারেন
PM> Install-Package WpfAnimatedGif
এবং এটি ব্যবহার করার জন্য, উইন্ডোতে একটি নতুন নেমস্পেসে যেখানে আপনি gif চিত্রটি যুক্ত করতে চান এবং নীচের মত ব্যবহার করতে পারেন
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gif="http://wpfanimatedgif.codeplex.com" <!-- THIS NAMESPACE -->
Title="MainWindow" Height="350" Width="525">
<Grid>
<!-- EXAMPLE USAGE BELOW -->
<Image gif:ImageBehavior.AnimatedSource="Images/animated.gif" />
প্যাকেজটি সত্যই ঝরঝরে, আপনি নীচের মতো কিছু বৈশিষ্ট্য সেট করতে পারেন
<Image gif:ImageBehavior.RepeatBehavior="3x"
gif:ImageBehavior.AnimatedSource="Images/animated.gif" />
এবং আপনি এটি আপনার কোডগুলিতেও ব্যবহার করতে পারেন:
var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(fileName);
image.EndInit();
ImageBehavior.SetAnimatedSource(img, image);
সম্পাদনা: সিলভারলাইট সমর্থন
জোশ 2112 এর মন্তব্য অনুসারে আপনি যদি নিজের সিলভারলাইট প্রকল্পে অ্যানিমেটেড জিআইএফ সমর্থন যুক্ত করতে চান তবে github.com/XamlAnimatedGif/XamlAnimatedGif ব্যবহার করুন
img
এখানে কি ?
আমি চিত্র নিয়ন্ত্রণ প্রসারিত এবং জিএফ ডিকোডার ব্যবহার করে একটি সমাধান পোস্ট করি। জিআইএফ ডিকোডারটির একটি ফ্রেমের সম্পত্তি রয়েছে। আমি FrameIndex
সম্পত্তি সঞ্চারিত । ইভেন্টটি ChangingFrameIndex
উত্সের বৈশিষ্ট্যটিকে ফ্রেমের সাথে সংযুক্ত করে FrameIndex
(এটি ডিকোডারে রয়েছে)। আমি অনুমান করি যে জিআইএফ প্রতি সেকেন্ডে 10 ফ্রেম রয়েছে।
class GifImage : Image
{
private bool _isInitialized;
private GifBitmapDecoder _gifDecoder;
private Int32Animation _animation;
public int FrameIndex
{
get { return (int)GetValue(FrameIndexProperty); }
set { SetValue(FrameIndexProperty, value); }
}
private void Initialize()
{
_gifDecoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
_animation = new Int32Animation(0, _gifDecoder.Frames.Count - 1, new Duration(new TimeSpan(0, 0, 0, _gifDecoder.Frames.Count / 10, (int)((_gifDecoder.Frames.Count / 10.0 - _gifDecoder.Frames.Count / 10) * 1000))));
_animation.RepeatBehavior = RepeatBehavior.Forever;
this.Source = _gifDecoder.Frames[0];
_isInitialized = true;
}
static GifImage()
{
VisibilityProperty.OverrideMetadata(typeof (GifImage),
new FrameworkPropertyMetadata(VisibilityPropertyChanged));
}
private static void VisibilityPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if ((Visibility)e.NewValue == Visibility.Visible)
{
((GifImage)sender).StartAnimation();
}
else
{
((GifImage)sender).StopAnimation();
}
}
public static readonly DependencyProperty FrameIndexProperty =
DependencyProperty.Register("FrameIndex", typeof(int), typeof(GifImage), new UIPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex)));
static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
{
var gifImage = obj as GifImage;
gifImage.Source = gifImage._gifDecoder.Frames[(int)ev.NewValue];
}
/// <summary>
/// Defines whether the animation starts on it's own
/// </summary>
public bool AutoStart
{
get { return (bool)GetValue(AutoStartProperty); }
set { SetValue(AutoStartProperty, value); }
}
public static readonly DependencyProperty AutoStartProperty =
DependencyProperty.Register("AutoStart", typeof(bool), typeof(GifImage), new UIPropertyMetadata(false, AutoStartPropertyChanged));
private static void AutoStartPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
(sender as GifImage).StartAnimation();
}
public string GifSource
{
get { return (string)GetValue(GifSourceProperty); }
set { SetValue(GifSourceProperty, value); }
}
public static readonly DependencyProperty GifSourceProperty =
DependencyProperty.Register("GifSource", typeof(string), typeof(GifImage), new UIPropertyMetadata(string.Empty, GifSourcePropertyChanged));
private static void GifSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
(sender as GifImage).Initialize();
}
/// <summary>
/// Starts the animation
/// </summary>
public void StartAnimation()
{
if (!_isInitialized)
this.Initialize();
BeginAnimation(FrameIndexProperty, _animation);
}
/// <summary>
/// Stops the animation
/// </summary>
public void StopAnimation()
{
BeginAnimation(FrameIndexProperty, null);
}
}
ব্যবহারের উদাহরণ (এক্সএএমএল):
<controls:GifImage x:Name="gifImage" Stretch="None" GifSource="/SomeImage.gif" AutoStart="True" />
Int32AnimationUsingKeyFrames
gf.Frames[0].MetaData.GetQuery("/grctlext/Delay")
(একটি ইউএসোর্ট যা শত শত সেকেন্ডে ফ্রেমের সময়কাল)
আমিও একটি অনুসন্ধান করেছি এবং পুরানো এমএসডিএন ফোরামে কেবল একটি থ্রেডে বেশ কয়েকটি ভিন্ন সমাধান পেয়েছি। (লিঙ্কটি আর কাজ করে না তাই আমি এটিকে সরিয়ে দিয়েছি)
কার্যকর করার পক্ষে সবচেয়ে সহজ মনে হচ্ছে একটি উইনফোর্ডস PictureBox
নিয়ন্ত্রণ ব্যবহার করা হয়েছে এবং এটি চলে গেছে (থ্রেড থেকে কয়েকটি জিনিস বদলানো হয়েছে, বেশিরভাগ ক্ষেত্রে এটি একই রকম)।
একটি রেফারেন্স যোগ করুন System.Windows.Forms
, WindowsFormsIntegration
এবং System.Drawing
আপনার প্রকল্পের প্রথম।
<Window x:Class="GifExample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wfi="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:winForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
Loaded="Window_Loaded" >
<Grid>
<wfi:WindowsFormsHost>
<winForms:PictureBox x:Name="pictureBoxLoading">
</winForms:PictureBox>
</wfi:WindowsFormsHost>
</Grid>
</Window >
তারপরে Window_Loaded
হ্যান্ডলারের মধ্যে, আপনি pictureBoxLoading.ImageLocation
যে চিত্রটি দেখাতে চান তার জন্য সম্পত্তি সেট করে দেবেন ।
private void Window_Loaded(object sender, RoutedEventArgs e)
{
pictureBoxLoading.ImageLocation = "../Images/mygif.gif";
}
MediaElement
নিয়ন্ত্রণ যে থ্রেড উল্লেখ করা হয়েছিল, কিন্তু এটি, উল্লেখ করা হয় যে এটি একটি বরং ভারী নিয়ন্ত্রণ নেই তাই অন্তত 2 homebrewed উপর ভিত্তি করে নিয়ন্ত্রণ সহ বিকল্প একটি নম্বর ছিল, Image
, নিয়ন্ত্রণ তাই এই সহজ হয়।
AllowTransparency="True"
। এটি আপনার মনে থাকা ফলাফলগুলি এনে দেবে কিনা তা অন্য বিষয়। আমি নিজে চেষ্টা করে দেখিনি, তবে আমি বাজি ধরব যে এটি WindowsFormsHost
একেবারেই স্বচ্ছ হবে না। বাকি Window
শক্তি। আমার মনে হয় আপনার এটি চেষ্টা করতে হবে।
এই ক্ষুদ্র অ্যাপটি সম্পর্কে কীভাবে: পিছনে কোড:
public MainWindow()
{
InitializeComponent();
Files = Directory.GetFiles(@"I:\images");
this.DataContext= this;
}
public string[] Files
{get;set;}
XAML:
<Window x:Class="PicViewer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="175" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox x:Name="lst" ItemsSource="{Binding Path=Files}"/>
<MediaElement Grid.Column="1" LoadedBehavior="Play" Source="{Binding ElementName=lst, Path=SelectedItem}" Stretch="None"/>
</Grid>
</Window>
<MediaElement LoadedBehavior="Play" Source="{Binding MyGifFile}" >
- মাইজিফফাইলটি আমার অ্যানিমেটেড জিআইএফের ফাইলের নাম (এবং পথ)।
ListBox
বা মোটেও বাঁধতে বিরক্ত করে ? আমি বাঁধাই ছাড়াই এটি চেষ্টা করেছিলাম, কেবল উত্সটিতে ফাইলের পাথ রেখেছি এবং এটি উপস্থিত হয়, তবে প্রাণবন্ত হয় না। আমি যদি বাইন্ডিং ব্যবহার করি, এমনকি ListBox
এটির সাথেও , এটি আমার কাছে একেবারেই আসে না - এটি আমার একটি ব্যতিক্রম দেয় যে আমার ফাইলের পথটি ভুল, যদিও এটি প্রদর্শিত হওয়ার পরে আমি একই ব্যবহার করি।
এটি ব্যবহার করা খুব সহজ <MediaElement>
:
<MediaElement Height="113" HorizontalAlignment="Left" Margin="12,12,0,0"
Name="mediaElement1" VerticalAlignment="Top" Width="198" Source="C:\Users\abc.gif"
LoadedBehavior="Play" Stretch="Fill" SpeedRatio="1" IsMuted="False" />
public string SpinnerLogoPath => Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Assets\images\mso_spinninglogo_blue_2.gif");
। ফাইলটি বিল্ড = কনটেন্টে সেট করা এবং আউটপুট ডিরেক্টরিতে অনুলিপি করা নিশ্চিত করুন।
এখানে আমার অ্যানিমেটেড চিত্র নিয়ন্ত্রণের সংস্করণ। চিত্র উত্স নির্দিষ্ট করার জন্য আপনি স্ট্যান্ডার্ড সম্পত্তি উত্স ব্যবহার করতে পারেন। আমি আরও উন্নতি করেছি। আমি একজন রাশিয়ান, প্রকল্পটি রাশিয়ান তাই মন্তব্যগুলিও রাশিয়ান ভাষায়। তবে যাইহোক আপনার মন্তব্য ছাড়া সমস্ত কিছু বুঝতে সক্ষম হওয়া উচিত। :)
/// <summary>
/// Control the "Images", which supports animated GIF.
/// </summary>
public class AnimatedImage : Image
{
#region Public properties
/// <summary>
/// Gets / sets the number of the current frame.
/// </summary>
public int FrameIndex
{
get { return (int) GetValue(FrameIndexProperty); }
set { SetValue(FrameIndexProperty, value); }
}
/// <summary>
/// Gets / sets the image that will be drawn.
/// </summary>
public new ImageSource Source
{
get { return (ImageSource) GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
#endregion
#region Protected interface
/// <summary>
/// Provides derived classes an opportunity to handle changes to the Source property.
/// </summary>
protected virtual void OnSourceChanged(DependencyPropertyChangedEventArgs aEventArgs)
{
ClearAnimation();
BitmapImage lBitmapImage = aEventArgs.NewValue as BitmapImage;
if (lBitmapImage == null)
{
ImageSource lImageSource = aEventArgs.NewValue as ImageSource;
base.Source = lImageSource;
return;
}
if (!IsAnimatedGifImage(lBitmapImage))
{
base.Source = lBitmapImage;
return;
}
PrepareAnimation(lBitmapImage);
}
#endregion
#region Private properties
private Int32Animation Animation { get; set; }
private GifBitmapDecoder Decoder { get; set; }
private bool IsAnimationWorking { get; set; }
#endregion
#region Private methods
private void ClearAnimation()
{
if (Animation != null)
{
BeginAnimation(FrameIndexProperty, null);
}
IsAnimationWorking = false;
Animation = null;
Decoder = null;
}
private void PrepareAnimation(BitmapImage aBitmapImage)
{
Debug.Assert(aBitmapImage != null);
if (aBitmapImage.UriSource != null)
{
Decoder = new GifBitmapDecoder(
aBitmapImage.UriSource,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
}
else
{
aBitmapImage.StreamSource.Position = 0;
Decoder = new GifBitmapDecoder(
aBitmapImage.StreamSource,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
}
Animation =
new Int32Animation(
0,
Decoder.Frames.Count - 1,
new Duration(
new TimeSpan(
0,
0,
0,
Decoder.Frames.Count / 10,
(int) ((Decoder.Frames.Count / 10.0 - Decoder.Frames.Count / 10) * 1000))))
{
RepeatBehavior = RepeatBehavior.Forever
};
base.Source = Decoder.Frames[0];
BeginAnimation(FrameIndexProperty, Animation);
IsAnimationWorking = true;
}
private bool IsAnimatedGifImage(BitmapImage aBitmapImage)
{
Debug.Assert(aBitmapImage != null);
bool lResult = false;
if (aBitmapImage.UriSource != null)
{
BitmapDecoder lBitmapDecoder = BitmapDecoder.Create(
aBitmapImage.UriSource,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
lResult = lBitmapDecoder is GifBitmapDecoder;
}
else if (aBitmapImage.StreamSource != null)
{
try
{
long lStreamPosition = aBitmapImage.StreamSource.Position;
aBitmapImage.StreamSource.Position = 0;
GifBitmapDecoder lBitmapDecoder =
new GifBitmapDecoder(
aBitmapImage.StreamSource,
BitmapCreateOptions.PreservePixelFormat,
BitmapCacheOption.Default);
lResult = lBitmapDecoder.Frames.Count > 1;
aBitmapImage.StreamSource.Position = lStreamPosition;
}
catch
{
lResult = false;
}
}
return lResult;
}
private static void ChangingFrameIndex
(DependencyObject aObject, DependencyPropertyChangedEventArgs aEventArgs)
{
AnimatedImage lAnimatedImage = aObject as AnimatedImage;
if (lAnimatedImage == null || !lAnimatedImage.IsAnimationWorking)
{
return;
}
int lFrameIndex = (int) aEventArgs.NewValue;
((Image) lAnimatedImage).Source = lAnimatedImage.Decoder.Frames[lFrameIndex];
lAnimatedImage.InvalidateVisual();
}
/// <summary>
/// Handles changes to the Source property.
/// </summary>
private static void OnSourceChanged
(DependencyObject aObject, DependencyPropertyChangedEventArgs aEventArgs)
{
((AnimatedImage) aObject).OnSourceChanged(aEventArgs);
}
#endregion
#region Dependency Properties
/// <summary>
/// FrameIndex Dependency Property
/// </summary>
public static readonly DependencyProperty FrameIndexProperty =
DependencyProperty.Register(
"FrameIndex",
typeof (int),
typeof (AnimatedImage),
new UIPropertyMetadata(0, ChangingFrameIndex));
/// <summary>
/// Source Dependency Property
/// </summary>
public new static readonly DependencyProperty SourceProperty =
DependencyProperty.Register(
"Source",
typeof (ImageSource),
typeof (AnimatedImage),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure,
OnSourceChanged));
#endregion
}
আমি এই গ্রন্থাগারটি ব্যবহার করছি: https://github.com/XamlAnimatedGif/WpfAnimatedGif
প্রথমে আপনার প্রকল্পে লাইব্রেরি ইনস্টল করুন (প্যাকেজ ম্যানেজার কনসোল ব্যবহার করে):
PM > Install-Package WpfAnimatedGif
তারপরে, এই স্নিপেটটি এক্সএএমএল ফাইলটিতে ব্যবহার করুন:
<Window x:Class="WpfAnimatedGif.Demo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image gif:ImageBehavior.AnimatedSource="Images/animated.gif" />
...
আমি আশা করি সাহায্য করবে।
মূলত উপরে একই চিত্রবক্স সমাধান, তবে এবার আপনার প্রকল্পে একটি এম্বেডেড রিসোর্স ব্যবহার করার জন্য কোড-ব্যাক সহ:
এক্সএএমএল-তে:
<WindowsFormsHost x:Name="_loadingHost">
<Forms:PictureBox x:Name="_loadingPictureBox"/>
</WindowsFormsHost>
কোড পিছনে:
public partial class ProgressIcon
{
public ProgressIcon()
{
InitializeComponent();
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("My.Namespace.ProgressIcon.gif");
var image = System.Drawing.Image.FromStream(stream);
Loaded += (s, e) => _loadingPictureBox.Image = image;
}
}
আমি মাইক এশভার কোডটি সংশোধন করেছি এবং আমি এটিকে আরও ভালভাবে কাজ করার জন্য তৈরি করেছি You আপনি এটি 1frame jpg png bmp বা mutil-ফ্রেম gif দিয়ে ব্যবহার করতে পারেন you আপনি যদি একটি uri নিয়ন্ত্রণে বাঁধতে চান তবে ইউরিসোর্স বৈশিষ্ট্যগুলিকে আবদ্ধ করতে চান বা আপনি কোনও ইন-ইন-বেঁধে রাখতে চান মেমরি স্ট্রিম যা আপনি উত্সটিকে বেঁধে রাখছেন এটি একটি বিটম্যাপাইমেজ।
/// <summary>
/// Элемент управления "Изображения", поддерживающий анимированные GIF.
/// </summary>
public class AnimatedImage : Image
{
static AnimatedImage()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(AnimatedImage), new FrameworkPropertyMetadata(typeof(AnimatedImage)));
}
#region Public properties
/// <summary>
/// Получает/устанавливает номер текущего кадра.
/// </summary>
public int FrameIndex
{
get { return (int)GetValue(FrameIndexProperty); }
set { SetValue(FrameIndexProperty, value); }
}
/// <summary>
/// Get the BitmapFrame List.
/// </summary>
public List<BitmapFrame> Frames { get; private set; }
/// <summary>
/// Get or set the repeatBehavior of the animation when source is gif formart.This is a dependency object.
/// </summary>
public RepeatBehavior AnimationRepeatBehavior
{
get { return (RepeatBehavior)GetValue(AnimationRepeatBehaviorProperty); }
set { SetValue(AnimationRepeatBehaviorProperty, value); }
}
public new BitmapImage Source
{
get { return (BitmapImage)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public Uri UriSource
{
get { return (Uri)GetValue(UriSourceProperty); }
set { SetValue(UriSourceProperty, value); }
}
#endregion
#region Protected interface
/// <summary>
/// Provides derived classes an opportunity to handle changes to the Source property.
/// </summary>
protected virtual void OnSourceChanged(DependencyPropertyChangedEventArgs e)
{
ClearAnimation();
BitmapImage source;
if (e.NewValue is Uri)
{
source = new BitmapImage();
source.BeginInit();
source.UriSource = e.NewValue as Uri;
source.CacheOption = BitmapCacheOption.OnLoad;
source.EndInit();
}
else if (e.NewValue is BitmapImage)
{
source = e.NewValue as BitmapImage;
}
else
{
return;
}
BitmapDecoder decoder;
if (source.StreamSource != null)
{
decoder = BitmapDecoder.Create(source.StreamSource, BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnLoad);
}
else if (source.UriSource != null)
{
decoder = BitmapDecoder.Create(source.UriSource, BitmapCreateOptions.DelayCreation, BitmapCacheOption.OnLoad);
}
else
{
return;
}
if (decoder.Frames.Count == 1)
{
base.Source = decoder.Frames[0];
return;
}
this.Frames = decoder.Frames.ToList();
PrepareAnimation();
}
#endregion
#region Private properties
private Int32Animation Animation { get; set; }
private bool IsAnimationWorking { get; set; }
#endregion
#region Private methods
private void ClearAnimation()
{
if (Animation != null)
{
BeginAnimation(FrameIndexProperty, null);
}
IsAnimationWorking = false;
Animation = null;
this.Frames = null;
}
private void PrepareAnimation()
{
Animation =
new Int32Animation(
0,
this.Frames.Count - 1,
new Duration(
new TimeSpan(
0,
0,
0,
this.Frames.Count / 10,
(int)((this.Frames.Count / 10.0 - this.Frames.Count / 10) * 1000))))
{
RepeatBehavior = RepeatBehavior.Forever
};
base.Source = this.Frames[0];
BeginAnimation(FrameIndexProperty, Animation);
IsAnimationWorking = true;
}
private static void ChangingFrameIndex
(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
AnimatedImage animatedImage = dp as AnimatedImage;
if (animatedImage == null || !animatedImage.IsAnimationWorking)
{
return;
}
int frameIndex = (int)e.NewValue;
((Image)animatedImage).Source = animatedImage.Frames[frameIndex];
animatedImage.InvalidateVisual();
}
/// <summary>
/// Handles changes to the Source property.
/// </summary>
private static void OnSourceChanged
(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
((AnimatedImage)dp).OnSourceChanged(e);
}
#endregion
#region Dependency Properties
/// <summary>
/// FrameIndex Dependency Property
/// </summary>
public static readonly DependencyProperty FrameIndexProperty =
DependencyProperty.Register(
"FrameIndex",
typeof(int),
typeof(AnimatedImage),
new UIPropertyMetadata(0, ChangingFrameIndex));
/// <summary>
/// Source Dependency Property
/// </summary>
public new static readonly DependencyProperty SourceProperty =
DependencyProperty.Register(
"Source",
typeof(BitmapImage),
typeof(AnimatedImage),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure,
OnSourceChanged));
/// <summary>
/// AnimationRepeatBehavior Dependency Property
/// </summary>
public static readonly DependencyProperty AnimationRepeatBehaviorProperty =
DependencyProperty.Register(
"AnimationRepeatBehavior",
typeof(RepeatBehavior),
typeof(AnimatedImage),
new PropertyMetadata(null));
public static readonly DependencyProperty UriSourceProperty =
DependencyProperty.Register(
"UriSource",
typeof(Uri),
typeof(AnimatedImage),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.AffectsMeasure,
OnSourceChanged));
#endregion
}
এটি একটি কাস্টম নিয়ন্ত্রণ। আপনার এটি ডাব্লুপিএফ অ্যাপ্লিকেশন প্রকল্পে তৈরি করতে হবে এবং শৈলীতে টেমপ্লেট ওভাররাইড মুছতে হবে।
আমার এই সমস্যাটি ছিল, যতক্ষণ না আমি আবিষ্কার করেছি যে ডাব্লুপিএফ 4 এ আপনি নিজের কীফ্রেম চিত্রের অ্যানিমেশনগুলি সিমুলেট করতে পারেন। প্রথমে আপনার অ্যানিমেশনটিকে চিত্রের একটি সিরিজে বিভক্ত করুন, তাদের "চিত্র 1.gif", "চিত্র 2, জিআইএফ" ইত্যাদির মতো শিরোনাম করুন। আপনার সমাধান সংস্থানগুলিতে এই চিত্রগুলি আমদানি করুন। আমি ধরে নিচ্ছি আপনি এগুলি চিত্রগুলির জন্য ডিফল্ট সংস্থান স্থানে রেখেছেন।
আপনি চিত্র নিয়ন্ত্রণ ব্যবহার করতে যাচ্ছেন। নিম্নলিখিত এক্সএএমএল কোডটি ব্যবহার করুন। আমি অপরিহার্য জিনিস মুছে ফেলেছি।
<Image Name="Image1">
<Image.Triggers>
<EventTrigger RoutedEvent="Image.Loaded"
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0:0:1" Storyboard.TargetProperty="Source" RepeatBehavior="Forever">
<DiscreteObjectKeyFrames KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image1.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:0.25">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image2.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:0.5">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image3.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:0.75">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image4.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
<DiscreteObjectKeyFrames KeyTime="0:0:1">
<DiscreteObjectKeyFrame.Value>
<BitmapImage UriSource="Images/Image5.gif"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrames>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Image.Triggers>
</Image>
আপনার পোস্ট জোয়েলের জন্য ধন্যবাদ, এটি আমাকে ডাব্লুপিএফ-এর অ্যানিমেটেড জিআইএফ-র সহায়তার অভাব সমাধানে সহায়তা করেছে। উইংসফর্মস এপিআই-এর কারণে চিত্রবক্সলয়েডিং-ইমেজ সম্পত্তি স্থাপনের সাথে আমার একটি সময় ছিল he
আমাকে আমার অ্যানিমেটেড জিআইএফ ইমেজটির বিল্ড অ্যাকশনটি "সামগ্রী" হিসাবে এবং অনুলিপি ডিরেক্টরিতে "নতুনভাবে অনুলিপি করুন" বা "সর্বদা" অনুলিপিতে সেট করতে হয়েছিল। তারপরে মেইন উইন্ডোতে () আমি এই পদ্ধতিটি কল করেছি। কেবল ইস্যুটি হ'ল যখন আমি প্রবাহটি নিষ্পত্তি করার চেষ্টা করেছি তখন এটি আমার চিত্রের পরিবর্তে আমাকে একটি লাল খাম গ্রাফিক দিয়েছে। আমাকে এই সমস্যাটি সমাধান করতে হবে। এটি একটি বিটম্যাপ চিত্রটি লোড করার এবং এটি একটি বিটম্যাপে রূপান্তর করার ব্যথা সরিয়ে দিয়েছে (যা স্পষ্টতই আমার অ্যানিমেশনটিকে মেরে ফেলেছে কারণ এটি আর জিআইএফ নয়)।
private void SetupProgressIcon()
{
Uri uri = new Uri("pack://application:,,,/WPFTest;component/Images/animated_progress_apple.gif");
if (uri != null)
{
Stream stream = Application.GetContentStream(uri).Stream;
imgProgressBox.Image = new System.Drawing.Bitmap(stream);
}
}
.ImageLocation
পরিবর্তে সেট করতে বলার দরকার ছিল .Image
। তার ভুল পদ্ধতি ছিল। .ImageLocation
ভিজ্যুয়াল স্টুডিও প্রকল্পের মূলটি কাজ করে, তাই বলে যে আপনার Images
ফোল্ডার রয়েছে, আপনার পথটি তখন imgBox.ImageLocation = "/Images/my.gif";
। আপনি একটি ফোল্ডার নামক থাকে তাহলে Views
যেখানে আপনি একটি দেখুন যে ইমেজ দেখাবে আছে, আপ অবস্থায় ফিরিয়ে আনতে Images
, আপনি 2 বিন্দু ব্যবহার করতে হবে চাই: imgBox.ImageLocation = "../Images/my.gif";
।
আমি উপরের সমস্ত উপায়ে চেষ্টা করেছি, তবে প্রত্যেকেরই স্বল্পতা রয়েছে এবং আপনারা সবাইকে ধন্যবাদ, আমি আমার নিজস্ব জিফআইমেজটি তৈরি করি:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media.Imaging;
using System.IO;
using System.Windows.Threading;
namespace IEXM.Components
{
public class GifImage : Image
{
#region gif Source, such as "/IEXM;component/Images/Expression/f020.gif"
public string GifSource
{
get { return (string)GetValue(GifSourceProperty); }
set { SetValue(GifSourceProperty, value); }
}
public static readonly DependencyProperty GifSourceProperty =
DependencyProperty.Register("GifSource", typeof(string),
typeof(GifImage), new UIPropertyMetadata(null, GifSourcePropertyChanged));
private static void GifSourcePropertyChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
(sender as GifImage).Initialize();
}
#endregion
#region control the animate
/// <summary>
/// Defines whether the animation starts on it's own
/// </summary>
public bool IsAutoStart
{
get { return (bool)GetValue(AutoStartProperty); }
set { SetValue(AutoStartProperty, value); }
}
public static readonly DependencyProperty AutoStartProperty =
DependencyProperty.Register("IsAutoStart", typeof(bool),
typeof(GifImage), new UIPropertyMetadata(false, AutoStartPropertyChanged));
private static void AutoStartPropertyChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
(sender as GifImage).StartAnimation();
else
(sender as GifImage).StopAnimation();
}
#endregion
private bool _isInitialized = false;
private System.Drawing.Bitmap _bitmap;
private BitmapSource _source;
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
private BitmapSource GetSource()
{
if (_bitmap == null)
{
_bitmap = new System.Drawing.Bitmap(Application.GetResourceStream(
new Uri(GifSource, UriKind.RelativeOrAbsolute)).Stream);
}
IntPtr handle = IntPtr.Zero;
handle = _bitmap.GetHbitmap();
BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
DeleteObject(handle);
return bs;
}
private void Initialize()
{
// Console.WriteLine("Init: " + GifSource);
if (GifSource != null)
Source = GetSource();
_isInitialized = true;
}
private void FrameUpdatedCallback()
{
System.Drawing.ImageAnimator.UpdateFrames();
if (_source != null)
{
_source.Freeze();
}
_source = GetSource();
// Console.WriteLine("Working: " + GifSource);
Source = _source;
InvalidateVisual();
}
private void OnFrameChanged(object sender, EventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(FrameUpdatedCallback));
}
/// <summary>
/// Starts the animation
/// </summary>
public void StartAnimation()
{
if (!_isInitialized)
this.Initialize();
// Console.WriteLine("Start: " + GifSource);
System.Drawing.ImageAnimator.Animate(_bitmap, OnFrameChanged);
}
/// <summary>
/// Stops the animation
/// </summary>
public void StopAnimation()
{
_isInitialized = false;
if (_bitmap != null)
{
System.Drawing.ImageAnimator.StopAnimate(_bitmap, OnFrameChanged);
_bitmap.Dispose();
_bitmap = null;
}
_source = null;
Initialize();
GC.Collect();
GC.WaitForFullGCComplete();
// Console.WriteLine("Stop: " + GifSource);
}
public void Dispose()
{
_isInitialized = false;
if (_bitmap != null)
{
System.Drawing.ImageAnimator.StopAnimate(_bitmap, OnFrameChanged);
_bitmap.Dispose();
_bitmap = null;
}
_source = null;
GC.Collect();
GC.WaitForFullGCComplete();
// Console.WriteLine("Dispose: " + GifSource);
}
}
}
ব্যবহার:
<localComponents:GifImage x:Name="gifImage" IsAutoStart="True" GifSource="{Binding Path=value}" />
যেহেতু এটি মেমরি ফাঁস হতে পারে না এবং এটি জিআইএফ চিত্রটির নিজস্ব সময় রেখাটি অ্যানিমেটেড করেছে, আপনি এটি চেষ্টা করতে পারেন।
IsAutoStart
, তবে অন্যথায়, চ্যাম্পের মতো কাজ করেছে!
পূর্বে, আমি একই সমস্যার মুখোমুখি হয়েছিলাম, .gif
আপনার প্রকল্পে আমার ফাইল চালানো দরকার ছিল । আমার দুটি পছন্দ ছিল:
উইনফোর্ডস থেকে পিকচারবক্স ব্যবহার করা
একটি তৃতীয় পক্ষের লাইব্রেরি যেমন কোডপ্লেক্স.কম থেকে ডাব্লুপিএফএনএমেটেডজিফ ব্যবহার করে।
সংস্করণটি PictureBox
আমার পক্ষে কাজ করে না এবং প্রকল্পটি এটির জন্য বাহ্যিক লাইব্রেরি ব্যবহার করতে পারে না। তাই আমি মাধ্যমে নিজের জন্য এটি তৈরি করা Bitmap
সাহায্যে ImageAnimator
। কারণ, স্ট্যান্ডার্ড ফাইলগুলির BitmapImage
প্লেব্যাক সমর্থন করে না .gif
।
সম্পূর্ণ উদাহরণ:
XAML
<Window x:Class="PlayGifHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="MainWindow_Loaded">
<Grid>
<Image x:Name="SampleImage" />
</Grid>
</Window>
Code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
Bitmap _bitmap;
BitmapSource _source;
private BitmapSource GetSource()
{
if (_bitmap == null)
{
string path = Directory.GetCurrentDirectory();
// Check the path to the .gif file
_bitmap = new Bitmap(path + @"\anim.gif");
}
IntPtr handle = IntPtr.Zero;
handle = _bitmap.GetHbitmap();
return Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
_source = GetSource();
SampleImage.Source = _source;
ImageAnimator.Animate(_bitmap, OnFrameChanged);
}
private void FrameUpdatedCallback()
{
ImageAnimator.UpdateFrames();
if (_source != null)
{
_source.Freeze();
}
_source = GetSource();
SampleImage.Source = _source;
InvalidateVisual();
}
private void OnFrameChanged(object sender, EventArgs e)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(FrameUpdatedCallback));
}
}
Bitmap
ইউআরআই নির্দেশকে সমর্থন করে না , তাই আমি .gif
বর্তমান ডিরেক্টরি থেকে ফাইল লোড করি ।
GifImage.Initialize()
পদ্ধতির ছোট উন্নতি , যা জিআইএফ মেটাডেটা থেকে যথাযথ ফ্রেমের সময় পড়ে reads
private void Initialize()
{
_gifDecoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
int duration=0;
_animation = new Int32AnimationUsingKeyFrames();
_animation.KeyFrames.Add(new DiscreteInt32KeyFrame(0, KeyTime.FromTimeSpan(new TimeSpan(0))));
foreach (BitmapFrame frame in _gifDecoder.Frames)
{
BitmapMetadata btmd = (BitmapMetadata)frame.Metadata;
duration += (ushort)btmd.GetQuery("/grctlext/Delay");
_animation.KeyFrames.Add(new DiscreteInt32KeyFrame(_gifDecoder.Frames.IndexOf(frame)+1, KeyTime.FromTimeSpan(new TimeSpan(duration*100000))));
}
_animation.RepeatBehavior = RepeatBehavior.Forever;
this.Source = _gifDecoder.Frames[0];
_isInitialized = true;
}
আমি নিশ্চিত না যে এটির সমাধান হয়েছে কিনা তবে সবচেয়ে ভাল উপায় হ'ল ডাব্লুপিএফএনিমেটেডজিড লাইব্রেরি ব্যবহার করা । এটি ব্যবহার করা খুব সহজ, সহজ এবং সোজা এগিয়ে। এটির পিছনে কোডে কেবলমাত্র এক্সএএমএল কোডের 2 লাইন এবং সি # কোডের প্রায় 5 লাইন প্রয়োজন।
এটি কীভাবে এটি ব্যবহার করা যেতে পারে তার সমস্ত প্রয়োজনীয় বিবরণ আপনি দেখতে পাবেন। আমি হুইলটি পুনরায় উদ্ভাবনের পরিবর্তে এটিও ব্যবহার করেছি
ডাব্লুপিএফএনিমেটেডজিফের ব্যবহারের সুপারিশ করে এমন প্রধান প্রতিক্রিয়ায় যুক্ত করে , অ্যানিমেশনটি বাস্তবায়িত হয় তা নিশ্চিত করতে আপনি যদি কোনও জিআইএফ দিয়ে কোনও চিত্র অদলবদল করে থাকেন তবে আপনাকে অবশ্যই নিম্নলিখিত লাইনগুলি যুক্ত করতে হবে :
ImageBehavior.SetRepeatBehavior(img, new RepeatBehavior(0));
ImageBehavior.SetRepeatBehavior(img, RepeatBehavior.Forever);
সুতরাং আপনার কোডটি দেখতে পাবেন:
var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(fileName);
image.EndInit();
ImageBehavior.SetAnimatedSource(img, image);
ImageBehavior.SetRepeatBehavior(img, new RepeatBehavior(0));
ImageBehavior.SetRepeatBehavior(img, RepeatBehavior.Forever);
আমার কোড পরীক্ষা করুন, আমি আশা করি এটি আপনাকে সহায়তা করেছে :)
public async Task GIF_Animation_Pro(string FileName,int speed,bool _Repeat)
{
int ab=0;
var gif = GifBitmapDecoder.Create(new Uri(FileName), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
var getFrames = gif.Frames;
BitmapFrame[] frames = getFrames.ToArray();
await Task.Run(() =>
{
while (ab < getFrames.Count())
{
Thread.Sleep(speed);
try
{
Dispatcher.Invoke(() =>
{
gifImage.Source = frames[ab];
});
if (ab == getFrames.Count - 1&&_Repeat)
{
ab = 0;
}
ab++;
}
catch
{
}
}
});
}
অথবা
public async Task GIF_Animation_Pro(Stream stream, int speed,bool _Repeat)
{
int ab = 0;
var gif = GifBitmapDecoder.Create(stream , BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
var getFrames = gif.Frames;
BitmapFrame[] frames = getFrames.ToArray();
await Task.Run(() =>
{
while (ab < getFrames.Count())
{
Thread.Sleep(speed);
try
{
Dispatcher.Invoke(() =>
{
gifImage.Source = frames[ab];
});
if (ab == getFrames.Count - 1&&_Repeat)
{
ab = 0;
}
ab++;
}
catch{}
}
});
}
ডাব্লুপিএফ-এ অপেক্ষার অ্যানিমেশনের বিকল্প হ'ল:
<ProgressBar Height="20" Width="100" IsIndeterminate="True"/>
এটি একটি অ্যানিমেটেড অগ্রগতি বার প্রদর্শন করবে।