02-10-12, 06:46 PM
كاتب الموضوع : silverlight
الموضوع : الصور المتحركة في الدوت نت Animationاللغة المستخدمة: الفيجوال بيسك
التطبيق: فيجوال استوديو 2008
الدوت نت : .Net Framework 3.5
مـقـدمـة:
اليوم سنناقش نفس الموضوع ولكن برؤية تختلف قليلا عن ما هو موجود في الجزء الأول.
أيضا سوف نناقش أفكارا إضافية يمكن استخدامها للتعامل مع الصور Image Processing ورسمها بالشكل الذي نريده علي أن تكون المحصلة النهائية هي بناء كونترول يمكن إستخدامه في برامجنا
اعتقد أن الغالبية العظمي من مستخدمي الكمبيوتر وبشكل ما قد إستخدم أو تعامل مع برنامج PowerPoint وهذا البرنامج يسمح للمستخدم ببناء ملفات علي شكل Slides
وأيضا داخل هذه Slides يستطيع المستخدم أن يقوم بتحريك الصور والكلمات من إتجاهات مختلفة بحيث يحصل في النهاية علي ملفات ذو طابع خاص وغالبا ما تستخدم هذه الملفات في الدعاية أو الإعلان عن أي شئ ولكن بشكل لطيف
و هذا سيكون هدفنا من المقال وهو أن نتعلم كيفية بناء كونترول بسيط يمكن أن نستخدمه ليعمل بمثابة Slide ومن ثم نستخدم هذا الكونترول في برامجنا المختلفة وبالتالي نضيف لمسة جمالية إلي برامجنا وكل ذلك سيحدث باستخدام الدوت نت وتحديدا باستخدام +GDI
كما يعلم الجميع أن فكرة الحركة Animation مبنية علي إستخدام Timer ومن ثم نستخدم هذا Timer في تحريك أي شئ نريده مثل سلسلة من الصور أو الكلمات أو أي شئ أخر وبالتالي نعطي الإيحاء بعملية الحركة
وبناء Slides مثل الموجودة في برنامج Power Point تستخدم نفس التكنولوجيا أو نفس الأسلوب تقريبا فهي تعتمد علي Timer ومن ثم يتم رسم أي شئ مثل الصور أو Text أو أي شئ أخر باستخدام +GDI
ما هو الدور الذي تقوم به +GDI ؟
ربما قد يتساءل البعض ما هو دور أو ماهية علاقة +GDI بموضوعنا هذا.
في واقع الأمر تعتبر +GDI هي قلب الدوت نت وذلك من وجهة نظري الشخصية بل قد تكون هي قلب تكنولوجيا البرمجة بشكل عام فبدونها لربما لم يكن هناك ما نطلق عليه بالنوافذ Windows علي الإطلاق فهي المسئولة عن عمليات الرسم في الكمبيوتر وذلك إما علي سطح الكونترول أو علي سطح الفورم أو علي سطح جهاز الكمبيوتر نفسه وأرجو أن تسامحوني إن ذهبت في إعتقادي إلي أن من لم يتعلم كيفية إستخدام +GDI فهو لم يتعلم إلا القليل
ولكي نجيب علي هذا السؤال الذي طرحناه سوف نعطي مجموعة من الأمثلة التي سوف توضح لنا الدور الذي تلعبه +GDI بشكل عام وهذه الأمثلة ستكون في صورة أسئلة مختلفة ومن ثم سنحاول الإجابة عليها لتوضيح المغزى من الدور الذي تلعبه +GDI وهذه الأسئلة أيضا سوف تمثل النواة لما سوف نفعله لاحقا عند بناء الكونترول الذي سوف نستخدمه في عرض الصور كما يحدث في برنامج Power Point
أيضا معظم الأكواد التي سوف نكتبها يمكن لكم أن تعيدوا بناؤها علي شكل دوال Functions ومن ثم تستخدمونها في عمليات التعامل مع الصور
السؤال الأول:
هل من الممكن إعادة رسم صورة في أي شكل نريده؟
بالتأكيد نستطيع أن نرسم أي شئ في الشكل الذي نريد والمسئول عن كيفية تنفيذ ذلك هو GraphicsPath Class والمثال التالي يوضح ذلك
لنفترض أنه لدينا صورة ما Image ونريد أن نرسمها بحيث تظهر في شكل دائري أو علي شكل متوازي أضلاع أو خلافه فكيف نفعل ذلك باستخدام GraphicsPath Class . الكود التالي يوضح ذلك
كود :
Public Class Form1
' Create image
Private bmp As New Bitmap(My.Resources.baby_5)
End Class
كود :
Private Sub DrawCircularShape(ByVal g As Graphics)
' Create graphics path.
Dim path As New Drawing2D.GraphicsPath()
' Create rectangle.
Dim rect As New Rectangle(100, 10, 100, 100)
' add the rectangle to the graphics path.
path.AddEllipse(rect)
' fill the graphics path with red color
Using sb As New SolidBrush(Color.Red)
g.FillPath(sb, path)
End Using
' Set clipping region to path, region is replaced by another use combine mode to do that
g.SetClip(path, Drawing2D.CombineMode.Replace)
' dispose the path
path.Dispose()
' draw the image inside rectangle
g.DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel)
End Sub
ثم تم إضافة هذا المستطيل Rectangle الي المسار GraphicsPath ولكن علي شكل Ellipse
ثم تم رسم أو ملأ هذا المسار GraphicsPath باللون الأحمر
ثم استخدمنا SetClip لتحديد المنطقة التي تحدث بها عملية الرسم
ومن ثم قمنا برسم الصورة Image داخل المستطيل Rectangle
أرجو أن تلاحظوا الدور الذي تلعبه كل من SetClip وأيضا CombineMode.Replace فهما تحددان أن عملية الرسم ستتم فقط داخل المسار المحدد وأيضا سيتم استبدال هذا المسار بشئ أخر
كود :
Private Sub DrawAnyShapePath(ByVal g As Graphics)
' Create graphics path.
Dim path As New Drawing2D.GraphicsPath()
path.AddLine(New Point(100, 100), New Point(200, 200))
path.AddLine(New Point(200, 200), New Point(100, 300))
path.AddLine(New Point(100, 300), New Point(0, 200))
path.CloseFigure()
' Create rectangle and its dimensions shall be located within path
Dim rect As New Rectangle(0, 100, 200, 200)
' Set clipping region to path, region is replaced by another use combine mode to do that
g.SetClip(path, Drawing2D.CombineMode.Replace)
' dispose the path
path.Dispose()
' draw the image inside rectangle
g.DrawImage(bmp, rect, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel)
End Sub
ثم تم رسم مجموعة من الخطوط داخل هذا المسار GraphicsPath
ثم تم رسم أو ملأ هذا المسار GraphicsPath باللون الأحمر
ثم استخدمنا SetClip لتحديد المنطقة التي تحدث بها عملية الرسم
ومن ثم قمنا برسم الصورة Image داخل المستطيل Rectangle
أرجو أن تلاحظوا وللمرة الثانية الدور الذي تلعبه كل من SetClip وأيضا CombineMode.Replace
حاول عزيزي القارئ أن تقوم بالتغيير في قيمة CombineMode لكي تكتشف أهميتها بنفسك
كود :
Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
DrawCircularShape(e.Graphics)
DrawAnyShapePath(e.Graphics)
End Sub
السؤال الثاني:
هل من الممكن رسم أي مسار GraphicsPath نريده؟
بالتأكيد نستطيع أن نرسم أي شكل نريده باستخدام GraphicsPath ولنفرض علي سبيل المثال أننا نريد أن نرسم مسار علي شكل حلزوني Spiral كل مع علينا فعله هو أن نحدد شكل المسار ثم نقوم بعملية الرسم وغالبا هذا الأمر يحتاج فقط لمعرفة جيدة بالعمليات الرياضية Mathematics و المثال التالي يوضح كيفية رسم الشكل الحلزوني
كود :
Public Class Form1
Private bmp As New Bitmap(My.Resources.baby_5)
Private m_percent As Double = 40
Private n As Single = 5
Private Path As Drawing2D.GraphicsPath
Private Sub DrawSpiralShape(ByVal g As Graphics)
Dim rect As New Rectangle(100, 100, 200, 200)
Dim angle As Double = n * (Math.PI * 2) / 100
Dim distance As Double = Math.Max(CDbl(rect.Width), CDbl(rect.Height)) / 100
Path = New Drawing2D.GraphicsPath(Drawing2D.FillMode.Winding)
Dim cx As Single = rect.Width / 2
Dim cy As Single = rect.Height / 2
Dim p1 As Double = m_percent - 100
Dim p2 As Double = m_percent
If p1 < 0 Then
p1 = 0
End If
Dim b As Double = angle * p2
Dim p3 As New PointF(CSng((cx + (p1 * distance * Math.Sin(b)))), CSng((cy + (p1 * distance * Math.Cos(b)))))
b = angle * p1
While (p1 <= p2)
Dim pt As New PointF(CSng((cx + (p1 * distance * Math.Cos(b)))), CSng((cy + (p1 * distance * Math.Sin(b)))))
Path.AddLine(p3, pt)
p3 = pt
p1 += 0.1
b += angle / 10
End While
Path.CloseAllFigures()
g.SetClip(Path, Drawing2D.CombineMode.Replace)
g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
g.DrawPath(Pens.Black, Path)
End Sub
Private Sub DrawImageInsideSpiralshape(ByVal g As Graphics)
Dim rectA As RectangleF = Path.GetBounds()
Dim rectB As Rectangle = New Rectangle(rectA.X, rectA.Y, rectA.Width, rectA.Height)
g.DrawImage(bmp, rectB, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel)
Path.Dispose()
End Sub
Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
DrawSpiralShape(e.Graphics)
DrawImageInsideSpiralshape(e.Graphics)
End Sub
End Class
السؤال الثالث:
هل من الممكن رسم أي تكست Text علي شكل مسار GraphicsPath ؟
بالتأكيد نستطيع أن نرسم أي تكست Text نريده باستخدام GraphicsPath ولنفرض علي سبيل المثال أننا نريد أن نرسم تكست ثم نريد أن نملأ هذا التكست بصورة ما. المثال التالي يوضح كيفية عمل ذلك
كود :
[align=left]Public Class Form1
Private bmp As New Bitmap(My.Resources.baby_5)
Private Sub DrawStringPathVertical(ByVal g As Graphics)
g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Dim txt As String = "GDI+"
Dim Path As New Drawing2D.GraphicsPath()
Path.AddString(txt, New FontFamily("Times New Roman"), FontStyle.Bold, 100, _
New Point(0, 0), New StringFormat(StringFormatFlags.DirectionVertical))
Using tb As New TextureBrush(bmp)
g.FillPath(tb, Path)
End Using
g.DrawPath(Pens.Black, Path)
Path.Flatten(New Drawing2D.Matrix(), 30.0F)
End Sub
Private Sub DrawStringPathHorizontal(ByVal g As Graphics)
g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
Dim txt As String = "GDI+"
Dim Path As New Drawing2D.GraphicsPath()
Path.AddString(txt, New FontFamily("Times New Roman"), FontStyle.Bold, 100, _
New Point(100, 0), New StringFormat(StringFormatFlags.NoClip))
Using tb As New TextureBrush(bmp)
g.FillPath(tb, Path)
End Using
g.TranslateTransform(0, 100)
g.DrawPath(Pens.Black, Path)
Path.Flatten(New Drawing2D.Matrix(), 30.0F)
End Sub
Private Sub Form1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
DrawStringPathVertical(e.Graphics)
DrawStringPathHorizontal(e.Graphics)
End Sub
End Class[/align]
أعتقد أن الأمثلة التالية كافية حتى الأن لتوضيح الدور الذي تلعبه +GDI بشكل عام فهدفنا من المقال ليس مناقشة +GDI علي نطاق واسع وخصوصا أنني أفترض أن قارئ المقال لدية خلفية مناسبة في التعامل مع أوامر الرسم المختلفة وعموما يجب علينا أن ندرس ونتفهم كل ما يختص بعمليات الرسم في الدوت نت وحينها سوف نستطيع أن نبني ونرسم الكثير من الأشياء الرائعة
الأن وبعد أن أعطينا بعضا من الأفكار السريعة للتعامل مع GraphicsPath لنبدأ في بناء الكونترول الذي سوف نستخدمه في عرض الصور علي شكل Slides كما يحدث في برنامج Power Point
يتبع في المشاركة التالية