05-10-12, 04:19 AM
كاتب الموضوع : نور نبهان
فن صناعة التأثيرات المتحركة
بسم الله الرحمن الرحيم
و أفضل الصلاة و أتم التسليم على سيدنا محمد واله وصحبه أجمعين
السلام عليكم ورحمة الله وبركاته
فن صناعة التأثيرات المتحركة
بسم الله الرحمن الرحيم
و أفضل الصلاة و أتم التسليم على سيدنا محمد واله وصحبه أجمعين
السلام عليكم ورحمة الله وبركاته
عندما كنت أرى بعض الصور الملحقة لبعض البرامج حيث تكون الصورة نفسها مقسمة إلى عدة أجزاء متساوية بحيث لو مررتها بسرعة تجد عدة أشكال لها ومثال ذلك الصورة التالية:
لطالما استوقفتني هذه الصورة وكيفية استدعائها ففكرت قليلا وقلت الأمر بسيط وذلك لو أننا قسمنا العرض على ثلاثة فسنحصل على عرض القطعة الواحدة وبذلك بإمكاني وضع IMAGBOX داخل PictureBox بعرض القطعة الواحدة Width ثم ازحته لليسار أو اليمين +-Left فسأحصل على القطعة الثانية وهكذا لكن الأمر يبدو مرهق شيئا ما فليس من المعقول أن أتتبع عرض كل صورة وأقوم بهذه العملية استمر قليلا لأجد نفس الصورة ولكن هذه المرة القطع مرتبة بطريقة علوية ومثال ذلك الصورة التالية :
فعدت لفكرتي البدائية السابقة لكن ببعض التعديل هذه المرة PictureBox و IMAGBOX ولكن سأتعامل مع الارتفاع Height للصورة بدل العرض وطبعا +-Top نفس الإجراء السابق ولكن الأمر مازال مرهق ومتعب كثيرا نزعت الفكرة من رأسي فليس في مخيلتي هذه التعقيدات ولو كانت الحسابات لها بسيطة كما أن هذه البرمجيات ما كانت لتتبع هذه الطريقة أليس كذلك ؟
حاولت التغلب على الأمرفأنا أريد وضع هذه الميزة في برنامجي لاستفيد من هذه الصور فتابعت قليلا لأجد أنني استطيع ذلك باستخدام gdi32 طبعا هذا في الفيجوال بيسك 6 وذلك بالدلالات السابقة بمعرفة العرض Width و الارتفاع Height وعدد الأقسام MaxFrames
صحيح بنفس المطالب ولكنني لا احتاج PictureBox و IMAGBOX وإنما تكفي PictureBox
جرب التالي vb6:
أضف الأدوات Command1 , Picture1 ثم أضف Picture2 وضع فيها الصورة التالية:
وضع الكود التالي :vb6
كود :
[align=left]Option Explicit
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const SRCCOPY = &HCC0020
Private bRun As Boolean
Private Sub Command1_Click()
Dim lIndex As Long
Dim lAnimWidth As Long
Dim lAnimHeight As Long
Dim lMaxFrames As Long
If Command1.Caption = "Start" Then ' Start the animation viewer
Command1.Caption = "Stop" ' Change the caption
bRun = True ' Set flag as Running
lAnimWidth = 100 ' Change these values
lAnimHeight = 90 ' to fit your animation
lMaxFrames = 10 '
Picture2.ScaleMode = vbPixels
Picture1.ScaleMode = vbPixels
Picture2.AutoRedraw = True
Picture1.AutoRedraw = True
Do: DoEvents
BitBlt Picture1.hDC, 0, 0, lAnimWidth, lAnimHeight, _
Picture2.hDC, 0, lIndex * lAnimHeight, SRCCOPY ' Copy the frame
Picture1.Refresh
Sleep 100 ' Short Pause
lIndex = lIndex + 1 ' Next Frame
If lIndex > lMaxFrames - 1 Then lIndex = 0 ' At last frame, go to first frame
Loop While bRun = True ' Loop until Stop button is pressed or form is unloaded
Else
Command1.Caption = "Start"
bRun = False ' Stop
End If
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
bRun = False ' Stop
End
End Sub[/align]
تحلحل الموضوع قليلا لكن الأمر مازال مبهم ليس من المعقول أن الإتباع كما فعلت بالكود السابق مللت فتركت الموضوع وبعدها أرى معظم الاعتماد في هذه الصور على الدايركت اكس فقلت هذا هو الأمر المخفي يقومون بتحريك هذه الصور أو الوصول لأحد الفريمات عن طريق الدايركت اكس .
ومما جعلني أقتنع أن المستخدم هو الدايركت أن الصور التي صرت ألاحظها ليست فقط طولية وعرضية وإنما أحيانا تكون شبكة كالصورة التالية :
رميت الأمر جانبا وتوقفت هنا و الأبرز أنني لا استطيع استخدام عمليات المراوغة كالعرض و الارتفاع لان هذا الأمر يقوم برفع ضغط الدم لدي كما أنني لا أحب التعامل مع الدايركت اكس والاهم سأرمي hDC الحل الأنسب لي لأنها لم تعد معتمدة في إطار الدوت نت والشكل الجديد و المبهر هو GDI+ لكنني لن أتعامل معه منذ البداية فلابد من بديل.
وصل الحل السريع في ركب قطار الأفكار .
وجدت هذه الأداة Microsoft PictureClip Control 6.0 للعمة ميكروسوفت رغم قدمها إلا أن اسمها Picture Clip يشد للبحث عن ماهية استخدامها فهي تحوي هذه الكلمة Clip يبدو أنها مفيدة
كما أنني لا أهتم فالفكرة التي كنت أدور حولها هي صنع فيديو أي عملية مونتاج أستخدم فيه الدوت نت بحيث أقوم بعمل عرض كامل وتصويره بأحد البرامج التي تلتقط الصور للشاشة وبذلك أكون وصلت للمطلوب .
بالإضافة للصورة ربما أفكر بوضع أصوات وبذلك يكتمل المطلوب لي , صور أستطيع التحكم بتحريكها في أي وقت أريد و أصوات لهذه الصور في عملية الأصوات سأعود أيضا قليلا للعمة ميكروسوفت واستخدم محبوبتي الصوتية MicrosoftMultimediaControl6.0
لماذا أحب هذه الأداة:
لأنني أولا أستطيع تشغيل الأصوات فيها
وكذلك الفيديو ضمن إطار PictureBox
والأهم وهو بيت القصيد استخدام Position
حيث يمكنني بالاعتماد عليه عندما يصل الصوت لموضع Position القيام بحركة أخرى عبر مؤقت وجمل شرطية.
تكونت أسس الفكرة الآن :
التحكم بالصور Microsoft PictureClip Control 6.0
التحكم بالصوت Microsoft Multimedia Control 6.0
الاعتماد على الوقت Timer لأجل المراقبة وتحريك المكان
جمل شرطية للقيام بالتحرك في الوقت المطلوب If
وسيساعدني أن الصور المتحركةGif في الدوت نت لا تحتاج لأي أدوات
المثال الأول لتوضيح استخدامPictureClip :
نضيف الأداة كما في الصورة:
زر أيمن عل صندوق الأدوات ثم ChooseItems
بعد إضافة الأداة لصندوق الأدوات .
أضف الأداة للنموذج AxPictureClip1
وأضف أيضا صندوق صورة PictureBox1 وزر أمر Button1 ومؤقت Timer1
عد لأداة AxPictureClip1 و أضف إليها صورة من خاصية Picture ولتكن مثلا الصورة الموجودة في الأعلى والتي تحوي لفظ الجلالة بعد إضافتها اضغط عليها بالزر الأيمن واختر خصائصها Properties فيظهر لك الصندوق التالي :
في هذا الصندوق يتضح المطلوب منا وهو إدخال عدد الصفوف Rows وعدد الأعمدة Cols لو لاحظت الصورة التي اتفقنا على إضافتها ستجدها تحوي عمود واحد و10صفوف تكرر فيها لفظ الجلالة وبذلك نضيف العدد للصناديق أو حسب كل صورة ففي هذه الصورة مثلا
ثلاثة أعمدة وصف واحد
وفي صورة الشبح التالية تحوي عمود واحد وثلاثة صفوف الأمر سهل وبمجرد النظر.
بعد إضافة الصورة وتعديل الخاصية للصفوف والأعمدة نتجه لكتابة الكود الأول لنا في الموضوع :
كود :
[align=left]Public Class Form1
Dim X As Short
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
X = X + 1
If X = 10 Then X = 0
PictureBox1.Image = AxPictureClip1.get_GraphicCell(X)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Timer1.Enabled = True
End Sub
End Class[/align]
يمكنني استدعاء قسم معين لنفرض أريد القسم الخامس أي الواقع في العمود الأول والصف الخامس فيكون رقمه 5*1=5
أضف زر أمر وصندوق صورة وجرب الكود :
كود :
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
PictureBox2.Image = AxPictureClip1.get_GraphicCell(5)
End Sub
ستجد القسم الخامس يطبع في الصورة وكذلك الأمر لأي قسم.
وبذلك ننتهي من أول فلم لنا في الموضوع حمل المشروع الأول