02-10-12, 06:59 PM
كاتب الموضوع : silverlight
الموضوع : الصور المتحركة في الدوت نت Animationاللغة المستخدمة: الفيجوال بيسك
التطبيق: فيجوال استوديو 2008
الدوت نت : .Net Framework 3.5
مـقـدمـة:
اليوم سنحاول أن نضيف بعض المؤثرات الإضافية لكن قبل ذلك لنتحدث عن Timer وأهميته في تحريك الصور
الكلاس System.Threading.Timer Class يمتلك دوال رائعة وتسمي CallBack Functions وبالرغم من أن هذا الكلاس يمتلك القليل من القدرات ولكن هذه القدرات ستظل لها أهميتها ويمكن توضيح هذه القدرات كالتالي
المقدرة علي استخدام وتحديد CallBack
المقدرة علي كيفية تحديد الفترة الزمنية المناسبة قبل تنفيذ CallBack
المقدرة علي كيفية تحديد الفترة الزمنية بين كل CallBack وأخر مثله
هذه القدرات الثلاثة أعلاه تعطيك قوة كبيرة جدا لكي لكي يكون لك اليد العليا في أن تتحكم في تسريع عمليات الرسم GDI+ Speed
هناك كلاس أخر له نفس الأهمية وهو System.Timers.Timer Class حيث يفضل البعض إستخدامه بدلا من System.Threading.Timer Class حيث هنا نقوم بعمل Hook مع الحدث Ellapsed Event ثم نقوم بتحديد ما يسمي Ellapsed Time ومن ثم نستخدمه في تسريع عمليات الرسم
عموما الكلاسان سيؤديان نفس الهدف والأمر بالنهاية متروك للمبرمج في إستخدام أي من الكلاسان
لنعطي مثالا علي كيفية استخدام كل من هذان الكلاسان
المثال الأول:
هذا المثال يوضح كيفية استخدام الكلاس System.Timers.Timer Class لكي نرسم شيئا ما علي سطح الفورم
والخطوات اتالية توضح كيفية عمل ذلك
1- نقوم بتعريف متغير بعبر عن Timer
كود :
Private m_timer As New System.Timers.Timer()كود :
Private Sub StartTimer(ByVal m_Interval As Integer)
AddHandler m_timer.Elapsed, AddressOf TimerTick
m_timer.Interval = m_Interval
m_timer.Enabled = True
End Subكود :
Private Sub TimerTick(ByVal source As Object, _
ByVal e As System.Timers.ElapsedEventArgs)
Invalidate()
End Subكود :
Private Sub Form2_Paint(ByVal sender As System.Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
Dim path As New Drawing2D.GraphicsPath()
Dim stringText As String = Date.Now
Dim family As New FontFamily("Verdana")
Dim myfontStyle As Integer = CInt(FontStyle.Bold)
Dim emSize As Integer = 20
Dim origin As New Point(0, 0)
Dim format As StringFormat = StringFormat.GenericDefault
path.AddString(stringText, family, myfontStyle, emSize, origin, format)
Using lgb As New Drawing2D.LinearGradientBrush(path.GetBounds(), _
Color.Cyan, Color.Blue, 90, 0)
e.Graphics.FillPath(lgb, path)
End Using
End Subكود :
Private Sub Form2_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
StartTimer(1000)
End Subالمثال الثاني:
هذا المثال يوضح كيفية استخدام الكلاس System.Threading.Timer Class لكي نرسم شيئا ما علي سطح الفورم
1- نقوم بتعريف متغير يشير الي Timer
كود :
Private ThreadTimer As System.Threading.Timerكود :
Private Sub StartTimer(ByVal Interval As Integer)
Dim CallBackTimer As New Threading.TimerCallback(AddressOf TimerTick)
ThreadTimer = New System.Threading.Timer(CallBackTimer, Nothing, 0, Interval)
End Subكيف نستفيد من الفكرة الموجودة في الأمثلة أعلاه في عملية Animation المثال التالي يوضح ذلك
المثال الثالث
1 - نقوم بتعريف بعض المتغيرات
كود :
Public Class frmTransition
Private m_timer As New System.Timers.Timer()
Private m_Steps As Single
Private m_startTime As DateTime
' .......... rest of code
End Classكود :
Private Sub StartTimer(ByVal m_Interval As Integer)
AddHandler m_timer.Elapsed, AddressOf TimerTick
m_timer.Interval = m_Interval
m_timer.Enabled = True
m_Steps = 0
m_startTime = DateTime.Now
Invalidate()
End Sub
' .......... rest of codeكود :
Private Sub TimerTick(ByVal source As Object, _
ByVal e As System.Timers.ElapsedEventArgs)
' define & calculate ellapsed time
Dim timeEllapsed As TimeSpan = DateTime.Now - m_startTime
' define animation time
'the lowest the value the highest the speed
Dim AnimationTime As Integer = 2
' calcualte transition steps
m_Steps = CSng((100.0F / AnimationTime * timeEllapsed.TotalSeconds))
' check transition steps value & fix it
If m_Steps > 100 Then
m_Steps = 100
End If
' invalidate the paint
Invalidate()
End Sub
' .......... rest of codeحيث هنا نقوم بتعريف صورة وتعريف مستطيل ثم نقوم برسم الجزء العلوي من الصورة ثم نقوم برسم الجزء السفلي من الصورة وعمليات الرسم هنا يتم ربطها مع المتغير m_Steps الذي قمنا بحساب قيمته في الخطو رقم 3 أعلاه حيث تم ربط هذا المتغير مع المتغير الذي يشير الي Timer
كود :
Private Sub frmTransition_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
' define transition bitmap
Dim bmp As New Bitmap(My.Resources.baby_5)
' define transition rectangle
Dim m_rect As New Rectangle(0, 0, 100, 100)
' draw the top part barns effect
' draw the top part of the image based on transition steps
' define the top part of destination rectangle
Dim destTopRect As New Rectangle(0, 0, m_rect.Width, CInt(m_rect.Height * m_Steps / 200))
' define the image top part source rectangle
Dim srcTopRect As New Rectangle(0, 0, bmp.Width, CInt(bmp.Height / 2))
' draw the top part of the image
e.Graphics.DrawImage(bmp, destTopRect, srcTopRect, GraphicsUnit.Pixel)
' let us repeat the steps above to draw the bottom part of the barns effect
' define the destination rectangle bottom part
Dim destBottomRect As New Rectangle(0, _
CInt(m_rect.Height - CInt(m_rect.Height * m_Steps / 200)), _
m_rect.Width, _
CInt((m_rect.Height * m_Steps / 200)))
' define the image's bottom part source rectangle
Dim srcBottomRect As New Rectangle(0, CInt(bmp.Height / 2), _
bmp.Width, CInt(bmp.Height / 2))
' draw the bottom part of the image
e.Graphics.DrawImage(bmp, destBottomRect, srcBottomRect, GraphicsUnit.Pixel)
End Sub5- أخيرا نمرر الإجراء StartTimer الي الحدث Load الخاص بالفورم
كود :
Private Sub frmTransition_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.Load
StartTimer(60)
End Subالمثال الرابع
والكود التالي يوضح كيفية رسم نفس حركة الستائر ولكن في إتجاه أفقي وعليك استبدال الكود التالي مع الكود الموجود في الحدث Paint في المثال الثالث أعلاه
كود :
Private Sub frmTransition_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
Dim bmp As New Bitmap(My.Resources.baby_5)
Dim m_rect As New Rectangle(0, 0, 100, 100)
' draw the left part barns effect
Dim destTopRect As New Rectangle(0, 0, CInt(m_rect.Width * m_Steps / 200), m_rect.Height)
Dim srcTopRect As New Rectangle(0, 0, CInt(bmp.Width / 2), bmp.Height)
e.Graphics.DrawImage(bmp, destTopRect, srcTopRect, GraphicsUnit.Pixel)
' draw the right part barns effect
Dim destBottomRect As New Rectangle(CInt(m_rect.Width - CInt(m_rect.Width * m_Steps / 200)), _
0, _
CInt((m_rect.Width * m_Steps / 200)), _
m_rect.Height)
Dim srcBottomRect As New Rectangle(CInt(bmp.Width / 2), 0, _
CInt(bmp.Width / 2), bmp.Height)
e.Graphics.DrawImage(bmp, destBottomRect, srcBottomRect, GraphicsUnit.Pixel)
End Subماذا لو قمنا بعمل خليط من الفكرة الموجودة بالمثال الثالث والموجودة بالمثال الرابع بالتأكيد سنحصل علي Animation مختلف تماما وعليك فقط استبدال الكود التالي مع الكود الموجود في الحدث Paint في المثال الثالث أعلاه
كود :
Private Sub frmTransition_Paint(ByVal sender As Object, _
ByVal e As PaintEventArgs) Handles MyBase.Paint
Dim bmp As New Bitmap(My.Resources.baby_5)
Dim m_rect As New Rectangle(0, 0, 100, 100)
' ------------------------------------------------------->
' draw the left part of the barn
Dim destLeftRect As New Rectangle(0, 0, CInt(m_rect.Width * m_Steps / 200), m_rect.Height)
Dim srcLeftRect As New Rectangle(0, 0, CInt(bmp.Width / 2), bmp.Height)
e.Graphics.DrawImage(bmp, destLeftRect, srcLeftRect, GraphicsUnit.Pixel)
' ------------------------------------------------------->
' draw the right part of the barn
Dim destRightRect As New Rectangle(CInt(m_rect.Width - CInt(m_rect.Width * m_Steps / 200)), _
0, _
CInt((m_rect.Width * m_Steps / 200)), _
m_rect.Height)
Dim srcRightRect As New Rectangle(CInt(bmp.Width / 2), 0, _
CInt(bmp.Width / 2), bmp.Height)
e.Graphics.DrawImage(bmp, destRightRect, srcRightRect, GraphicsUnit.Pixel)
' ------------------------------------------------------->
' draw the top part of the barn
Dim destTopRect As New Rectangle(0, 0, m_rect.Width, CInt(m_rect.Height * m_Steps / 200))
Dim srcTopRect As New Rectangle(0, 0, bmp.Width, CInt(bmp.Height / 2))
e.Graphics.DrawImage(bmp, destTopRect, srcTopRect, GraphicsUnit.Pixel)
' ------------------------------------------------------->
' draw the bottom part of the barn
Dim destBottomRect As New Rectangle(0, _
CInt(m_rect.Height - CInt(m_rect.Height * m_Steps / 200)), _
m_rect.Width, _
CInt((m_rect.Height * m_Steps / 200)))
Dim srcBottomRect As New Rectangle(0, CInt(bmp.Height / 2), _
bmp.Width, CInt(bmp.Height / 2))
e.Graphics.DrawImage(bmp, destBottomRect, srcBottomRect, GraphicsUnit.Pixel)
End Subعموما الأفكار اعلاه قد تبدو صعبة للمبتدئين ولكن لو تم تنفيذها بشكل دقيق ستكتشفون أن الأمر أسهل مما تتصورون وبالتالي يمكنكم التعديل والتلاعب بها كيفما شئتم ومن ثم تصنعون Animation الذي يناسبكم
بشكل عام لقد تطرقنا الي توضيح بعض الأفكار في المقالات السابقة وفي المثال المرفق ستجدون كمية لا بأس بها من الأفكار فهناك حوالي 28 فكرة Animation يمكن استخدامها للتعامل مع الصور يمكنكم دراستها فالهدف من المقالات هو إعطاء الفكرة لدراستها وليس إستخدامها بأسلوب القص واللصق فقط
بالمرفقات ستجدون نسخة كاملة من المشروع وطريقة استخدامه و الملف المرفق بنسخة الفيجوال استوديو 2008
يوجد سخة من المقال باللغة الانجليزيةعلي موقع CodeProject لمن يريد الاطلاع عليها يمكنه ذلك من اللينك التالي
المقال في موقع CodeProject
مع تحياتي للجميع
أخوكم عمر
