WPF, работа с анимацией
-
10 апреля 2011 г. 16:17Типичная проблемка, но не понял как ее реализовать, сильно уж намудрили с вроде-бы простыми элементами... Для начала, что лучше использовать для отображения анимации? RichTextBox или WebBrowser? И как вообще внести изменение содержания этих элементов? Зачем так надо было усложнять с RichTextBox... Если можно примерчик со строкой текста и анимированной картинкой из ресурсов (test.gif). Спасибо
- Изменено Siompc 19 апреля 2011 г. 8:22
Все ответы
-
10 апреля 2011 г. 19:04Отвечающий
что лучше использовать для отображения анимации? RichTextBox или WebBrowser?
Вопрос в корне не правильный. Для анимации в WPF не нужен специальный элемент.
Что бы тебе ответили на вопрос по анимации, то задай вопрос конкретнее.
На второй вопрос - если нужен именно RichTextBox, то изучай http://msdn.microsoft.com/ru-ru/library/ms748388.aspx
Или расскажи в чем состоит задача и тебе подскажут ее решение (может RichTextBox и не нужен). С WebBrowser из 4 фреймворка еще не сталкивался, ничего сказать не смогу.
-
11 апреля 2011 г. 9:32
Пример добавления анимированного изображения в RichTextBox (C#):
Xaml:
<Window x:Class="WpfApplication20.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> <RichTextBox Name="rtb" Width="200" Height="200" /> <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="397,45,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" /> </Grid> </Window>
Код:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Drawing; using System.Windows.Threading; using System.Windows.Interop; namespace WpfApplication20 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void button1_Click(object sender, RoutedEventArgs e) { AnimatedImageControl testImg = new AnimatedImageControl(@"D:\220px-Rotating_earth_(large).gif"); Paragraph p = new Paragraph(); p.Inlines.Add(new InlineUIContainer(testImg)); rtb.Document.Blocks.Add(p); } } public class AnimatedImageControl : System.Windows.Controls.Image { delegate void OnFrameChangedDelegate(); System.Drawing.Bitmap img = null; public AnimatedImageControl(string path) { img = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(path); Dispatcher.BeginInvoke(DispatcherPriority.Normal, new OnFrameChangedDelegate(OnUpdateSource)); System.Drawing.ImageAnimator.Animate(img, new EventHandler(OnFrameChanged)); } private void OnFrameChanged(object sender, EventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, new OnFrameChangedDelegate(OnFrameChangedInMainThread)); } private void OnUpdateSource() { BeginInit(); this.Source = this.GetBitmapSource(img); EndInit(); } private void OnFrameChangedInMainThread() { BeginInit(); System.Drawing.ImageAnimator.UpdateFrames(img); this.Source = this.GetBitmapSource(img); InvalidateVisual(); EndInit(); } private BitmapSource GetBitmapSource(Bitmap gdiBitmap) { return Imaging.CreateBitmapSourceFromHBitmap( gdiBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } } }
(Источник: AnimatedImageControl, пример использования)
Для связи [mail] -
12 апреля 2011 г. 14:21Какой ужас... а в VB можно как то перевести? Он ругается практически на все...
-
13 апреля 2011 г. 4:51Отвечающий
Это C#
Если Дмитрий правильно тебя понял и тебе нужна именно работа с анимированным изображением (gif например), то будем его просить перевести сам класс AnimatedImageControl на VB, ибо мне и самому не помешает!!!
Если тебе нужно что то другое, то поясняй что!
-
13 апреля 2011 г. 5:13
Да-да! Это как раз подходит. Необходимо вместе с текстом вставить в рич-текст-бокс анимацию. Этот вариант подходит лучше всего. Пробовал сам перевести, но понятия не имею как в VB написать это - img = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(path)
Возможно так:
Dim img as BitmapImage = System.Drawing.Image.FromFile(path)
Но так тоже выдает много ошибок.
-
13 апреля 2011 г. 5:24
1. Добавить в References dll System.Drawing
2.
Imports System.Windows.Threading Imports System.Drawing Imports System.Windows.Interop
3.
Public Class AnimatedImageControl Inherits System.Windows.Controls.Image Private Delegate Sub OnFrameChangedDelegate() Private img As System.Drawing.Bitmap = Nothing Public Sub New(path As String) img = DirectCast(System.Drawing.Image.FromFile(path), System.Drawing.Bitmap) Dispatcher.BeginInvoke(DispatcherPriority.Normal, New OnFrameChangedDelegate(AddressOf OnUpdateSource)) System.Drawing.ImageAnimator.Animate(img, New EventHandler(AddressOf OnFrameChanged)) End Sub Private Sub OnFrameChanged(sender As Object, e As EventArgs) Dispatcher.BeginInvoke(DispatcherPriority.Normal, New OnFrameChangedDelegate(AddressOf OnFrameChangedInMainThread)) End Sub Private Sub OnUpdateSource() BeginInit() Me.Source = Me.GetBitmapSource(img) EndInit() End Sub Private Sub OnFrameChangedInMainThread() BeginInit() System.Drawing.ImageAnimator.UpdateFrames(img) Me.Source = Me.GetBitmapSource(img) InvalidateVisual() EndInit() End Sub Private Function GetBitmapSource(gdiBitmap As Bitmap) As BitmapSource Return Imaging.CreateBitmapSourceFromHBitmap(gdiBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()) End Function End Class
Для связи [mail]- Предложено в качестве ответа LXGDARKMicrosoft Community Contributor, Editor 13 апреля 2011 г. 6:33
- Помечено в качестве ответа Siompc 16 апреля 2011 г. 9:55
- Снята пометка об ответе Siompc 19 апреля 2011 г. 8:20
- Помечено в качестве ответа Siompc 21 апреля 2011 г. 18:26
-
13 апреля 2011 г. 16:25
Оо, спасибо! Последний вопрос, почему работает только так
Public testImg As AnimatedSmilesControl = New AnimatedSmilesControl("D:\1.gif")
если попытаться изменить -
testImg = New AnimatedSmilesControl("D:\1.gif")
выдает ошибку при ображщении.
-
14 апреля 2011 г. 7:51Какую ошибку? и не очень понятно что и как вы пытаетесь изменить.
Для связи [mail] -
14 апреля 2011 г. 13:50
Public testImg As AnimatedSmilesControl = New AnimatedSmilesControl("D:\1.gif")
Grid.Children.Add(testImg)
Так работает...
Public testImg As AnimatedSmilesControl
testImg = New AnimatedSmilesControl("D:\1.gif")
Grid.Children.Add(testImg)
А так говорит что ссылается на экземпляр объекта
-
14 апреля 2011 г. 18:03Отвечающий
Сначала в классе AnimatedSmilesControl добавь конструктор New без параметров, а потом делай так
Public testImg As New AnimatedSmilesControl
testImg = New AnimatedSmilesControl("D:\1.gif")
Объясню почему не работает. Первый вариант, который работает равносилен записи Public testImg As New AnimatedSmilesControl("D:\1.gif"), то есть объявляется экземпляр класса, а во втором варианте нет объявления экземпляра класса (о чем свидетельствует зеленое волнистое подчеркивание под словом testImg). Это основы объектно-ориентированного программирования!!! Не плохо бы знать такие вещи.
-
19 апреля 2011 г. 8:20Не работает. Не класс, ни работа с ним:
Сначала в классе AnimatedSmilesControl добавь конструктор New без параметров, а потом делай так
Public testImg As New AnimatedSmilesControl
testImg = New AnimatedSmilesControl("D:\1.gif")
Если обьявить так - Public testImg As New AnimatedSmilesControl, требует аргумент path...
А класс анимации работает только в том случае, если анимация просто стоит и никаких действий не происходит. Что делать если надо изменить картинку на анимацию при наведении курсора? Выдает ошибку:
В GDI+ возникла ошибка общего вида.
Может что не так делаю? Вот код:
Private Sub GeneralStep_MouseEnter(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseEventArgs) Handles _
GeneralPicStep.MouseEnter
Dim Anim As New AnimatedControl(My.Computer.FileSystem.CurrentDirectory & "\Data\BU\StepOn.gif")
If BlockStepImg(0) = False Then 'Разрешено изменение?
GeneralPicStep.Source = Anim.Source
End If
End Sub
И что делать, если необходимо изменить изображение в классе AnimatedControl не при обьявлении переменной.
Dim Anim As AnimatedControl
Anim = New AnimatedControl("D:\1.gif")
Так не работает...
-
19 апреля 2011 г. 18:34Отвечающий
Во первых приведенный код это только часть истории вырванная из контекста, поэтому не все понятно.
Во вторых - класс AnimatedControl наследник класса Image и вот эта строка GeneralPicStep.Source = Anim.Source вообще не нужна. Там где в окне должно быть анимированное изображение нужно помещать экземпляр класса AnimatedControl
Короче мне пока не надо было, но спешл фо ю я переделал предложенный Дмитрием класс и щас пошагово расскажу че с ним делать.
Шаг первый: Добавляешь в проект файл класса и даешь ему название AnimatedImageControl. Содержимое заменяешь следующим кодом:
Imports System.Windows.Threading Imports System.Drawing Imports System.Windows.Interop Public Class AnimatedImageControl Inherits System.Windows.Controls.Image Private Delegate Sub OnFrameChangedDelegate() Private img As System.Drawing.Bitmap = Nothing Dim path As String Public Sub New() End Sub Public WriteOnly Property AnimPath As String Set(ByVal value As String) path = value img = DirectCast(System.Drawing.Image.FromFile(path), System.Drawing.Bitmap) Me.Source = Me.GetBitmapSource(img) End Set End Property Public Sub StarAnimation() img = DirectCast(System.Drawing.Image.FromFile(path), System.Drawing.Bitmap) Dispatcher.BeginInvoke(DispatcherPriority.Normal, New OnFrameChangedDelegate(AddressOf OnUpdateSource)) System.Drawing.ImageAnimator.Animate(img, New EventHandler(AddressOf OnFrameChanged)) End Sub Private Sub OnFrameChanged(ByVal sender As Object, ByVal e As EventArgs) Dispatcher.BeginInvoke(DispatcherPriority.Normal, New OnFrameChangedDelegate(AddressOf OnFrameChangedInMainThread)) End Sub Private Sub OnUpdateSource() BeginInit() Me.Source = Me.GetBitmapSource(img) EndInit() End Sub Private Sub OnFrameChangedInMainThread() BeginInit() System.Drawing.ImageAnimator.UpdateFrames(img) Me.Source = Me.GetBitmapSource(img) InvalidateVisual() EndInit() End Sub Private Function GetBitmapSource(ByVal gdiBitmap As Bitmap) As BitmapSource Return Imaging.CreateBitmapSourceFromHBitmap(gdiBitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()) End Function End Class
Класс переделан так, что бы его можно было добавлять в XALM.
Шах второй: идешь в XAML редактор нужного тебе окошка и в свойствах самого окна добавляешь следующую строчку:
xmlns:ac="clr-namespace:WpfApplication1" (где WpfApplication1 это имя твоего приложения)
а в месте где тебе нужен данный контрол пишешь следующее:
<ac:AnimatedImageControl x:Name="Нужное_имя" AnimPath="C:\путь к файлу.gif" Height="60"></ac:AnimatedImageControl>
Шаг третий: так как анимация еще не запущенна нужно вызвать процедуру StarAnimation (AnimControl1.StarAnimation) в любом месте кода, например в событии Window_Loaded
Можно было конечно сделать класс, так что бы он запускал анимацию сразу при задании пути к файлу, но тогда это мешало бы при построении интерфейса, поэтому на мой взгляд так лучше.
Конечно это все наброски. По ходу работы могут понадобится обработчики ошибок и т.д., но это уже дело наживное
- Помечено в качестве ответа Siompc 21 апреля 2011 г. 18:26
-
21 апреля 2011 г. 10:28
LXGDARK огромное спасибо! Я даже не знаю за что отвечает DirectCast ))) Уже переделал класс, остался последний вопрос. здесь изображение идет через путь на диске. А как нужно преобразовать процедуру что бы шло через ресурсы (по Uri) например ( AnimUri("/Image/Bu/BU_StepWait.gif") )
Public WriteOnly Property AnimUri As Uri
Set(ByVal value As Uri)
Try
ResUri = value
img = ????????
Me.Source = Me.GetBitmapSource(img)
Catch ex As Exception
Me.Source = Nothing
End Try
End Set
End PropertyЗагвоздка в этом месте...
-
21 апреля 2011 г. 11:07Отвечающий
Dim sinfo As Windows.Resources.StreamResourceInfo = Application.GetResourceStream(New Uri("/Image/Bu/BU_StepWait.gif", UriKind.Relative)) img = System.Drawing.Image.FromStream(sinfo.Stream)
- Помечено в качестве ответа Siompc 21 апреля 2011 г. 18:26
-
21 апреля 2011 г. 18:26Работает! :)

