تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
الكلاس التائه بين +GDI و الويندوز فورم Forms
#1
كاتب الموضوع : silverlight

الموضوع : ControlPaint الكلاس التائه بين +System.Windows.Forms & GDI
اللغة المستخدمة: الفيجوال بيسك
التطبيق: فيجوال استوديو 2005 و 2008
المستوي: التقييم متروك للقارئ
إعداد: مهندس / عمر أمين إبراهيم

------------------------------------------------------------------------------------------------
مقدمة:
الهدف من كتابة هذا الموضوع يتلخص في شئ واحد فقط ألا وهو كيف نبني ونطور كونترول Control يحمل ملامح وصفات خاصة أو صفات إضافية أو كيف نضيف الي الكونترول المختلفة الموجودة بالفعل
داخل الفيجوال استوديو سمات إضافية ومن ثم نستخدمها داخل البرامج التي نقوم بإنشائها لأغراض مختلفة.

إن استخدامي لكلمة الكلاس التائه هنا ليس الهدف منها إن هذا الكلاس كان مفقودا وتم اكتشافه عن طريق احد ما ولكن السبب في اختيار هذا المعني يكمن في شئ واحد فقط أن هذا الكلاس واقعيا ينتمي الي الويندوز فورم Windows Forms ولكن عناصره وخصائصه وسماته المختلفة قطعا تنتمي كليا الي +GD.

بشكل عام ومبسط هذا الكلاس يستخدم في تصميم كل من واجهات التطبيق User Interface و أيضا في تصميم العناصر المكونة لواجهة التطبيق User Interface Elements في الويندوز فورم Windows Forms.

وأمثله علي ذلك
- رسم الباتون Button
- رسم الكومبو بوكس باتون ComboButton
- رسم CheckBox
- رسم RadioButton
- رسم ScrollButton
- رسم DrawCaptionButton
- رسم DrawGrid
اعتقد قبل أن نناقش الموضوع أو ندخل في أي تفاصيل أخري ولكي نري الامر جيدا ونشعر بهذا الكلاس وأهميته أنصحك أخي القارئ أن تقوم بتنفيذ هذا المثال الصغير عمليا ثم تعود بعد ذلك لتكمل قراءة باقي الموضوع

المثال الأول:
نفتح مشروعا جديدا ونطلق عليه الاسم الذي نرغب وليكن علي سبيل المثال Control_Paint_Example_01
نضيف الي الفورم فقط Picture Box Control ونغير صفه واحده من صفاته وهي Dock ونجعلها Full أو نغير الخاصية عن كريق إضافة الكود عموما الامر متروك للقارئ ثم نضيف الكود التالي الي الفورم فيصبح الشكل النهائي للكود كالأتي.


كود :
Public Class Form1

Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint

ControlPaint.DrawCheckBox(e.Graphics, New Rectangle(10, 10, 50, 50), ButtonState.Checked)
ControlPaint.DrawCheckBox(e.Graphics, New Rectangle(70, 10, 30, 30), ButtonState.Normal)
ControlPaint.DrawCheckBox(e.Graphics, New Rectangle(110, 10, 20, 20), ButtonState.Checked)

ControlPaint.DrawButton(e.Graphics, New Rectangle(10, 80, 20, 20), ButtonState.Checked)
ControlPaint.DrawButton(e.Graphics, New Rectangle(50, 80, 20, 20), ButtonState.Flat)
ControlPaint.DrawButton(e.Graphics, New Rectangle(90, 80, 20, 20), ButtonState.Normal)
ControlPaint.DrawFocusRectangle(e.Graphics, New Rectangle(130, 80, 20, 20))

ControlPaint.DrawGrid(e.Graphics, New Rectangle(10, 120, 250, 50), New Size(5, 5), Color.Blue)
ControlPaint.DrawScrollButton(e.Graphics, New Rectangle(10, 180, 20, 20), ScrollButton.Left, ButtonState.Normal)
ControlPaint.DrawScrollButton(e.Graphics, New Rectangle(50, 180, 20, 20), ScrollButton.Max, ButtonState.Pushed)
ControlPaint.DrawScrollButton(e.Graphics, New Rectangle(90, 180, 20, 20), ScrollButton.Down, ButtonState.Pushed)

ControlPaint.DrawMenuGlyph(e.Graphics, New Rectangle(10, 220, 20, 20), MenuGlyph.Arrow)
ControlPaint.DrawMenuGlyph(e.Graphics, New Rectangle(50, 220, 20, 20), MenuGlyph.Checkmark)
ControlPaint.DrawMenuGlyph(e.Graphics, New Rectangle(90, 220, 20, 20), MenuGlyph.Arrow)
ControlPaint.DrawVisualStyleBorder(e.Graphics, New Rectangle(150, 200, 50, 50))

End Sub

End Class

عناصر الكلاس Class Members:
الآن سوف نستعرض سويا عناصر وصفات هذا الكونترول وطبعا كما قالت ميكروسوفت هذا الكلاس لا يمكن استخدام الوراثةInheriting معه كما يحدث مع الكونترول الاخري مثل الباتون و الكومبوبوكس الي أخره.

طرق الكلاس
CreateHBitmap16Bit
CreateHBitmapColorMask
Dark
CreateHBitmapTransparencyMask
DrawBorder
DarkDark
DrawBorder3D
DrawButton
DrawCaptionButton
DrawCheckBox
DrawComboButton
DrawContainerGrabHandle
DrawFocusRectangle
DrawGrabHandle
DrawGrid
DrawImageDisabled
DrawLockedFrame
DrawMenuGlyph
DrawMixedCheckBox
DrawRadioButton
DrawReversibleFrame
DrawReversibleLine
DrawScrollButton
DrawSelectionFrame
DrawSizeGrip
DrawStringDisabled
DrawVisualStyleBorder
Equals
FillReversibleRectangle
Finalize
GetHashCode
GetType
Light
LightLight
MemberwiseClone
ToString

صفات الكلاس

ContrastControlDark


و بالرغم أن الأوامر واضحة جدا لكن بعضها قد يوحي بالغموض أو عدم الوضوح أحيانا وعلي سبيل المثال CaptionButton لا يرسم باتون تحديدا ولكنه يرسم أشياء مثل Minimize, Close, Restore, Help Boxes أي باتون مثل التي نجدها دائما في أي فورم في الجزء الأيمن العلوي تحديدا وهي مفاتيح لإغلاق الفورم أو تكبيره الي أخره
في الواقع إن استخدام هذا الكلاس قد يوفر ساعات كثيرة من العمل باستخدام +GDI مثلا لو أردنا أن نرسم باتون بشكل معين فان ذلك قد يأخذ وقتا بالطريقة العادية لكن باستخدام هذا الكلاس فان ذلك قد يتم باستخدام اسطر قليله جدا من الكود
مثال علي ذلك لو أردنا رسم راديو باتون فان ذلك يتم بسطر واحد فقط وهو كالأتي

كود :
ControlPaint.DrawRadioButton(e.Graphics, New Rectangle(20, 20, 15, 15), ButtonState.Normal)
لكن يجب الوضع في الاعتبار شئ مهم جدا أن هذا الكلاس يرسم فقط الكونترول المطلوب لكن علي المبرمج طبعا إضافة أوامر أخري لكي يظهر الكونترول بالشكل المطلوب مثال علي ذلك الكلاس يرسم الباتون لكن المبرمج يجب أن يتعامل مع الكود لكي يظهر الباتون في حالاته المختلفة مثل Normal State, Pushed Stat وذلك عندما يقوم المستخدم بتمرير الماوس مثلا علي الكونترول

هناك شئ مهم جدا قد يربك المبرمج الذي قد يتعامل لأول مره مع هذا الكلاس حيث أن احدي الطرق الموجودة داخل هذا الكلاس وهي تحديدا DrawSelectionFrame وهذه الطريقة تستخدم بالشكل التالي


كود :
ControlPaint.DrawSelectionFrame(Graphics, active, outsideRect, insideRect, backColor)
بعض الكتب تقول أن هذا الكود فيه خطا وأن شركة ميكروسوفت قد قامت بعكس الكود ربما هذا صحيح لا اعلم في الواقع عموما البعض يقول أن الطريقة الصحيحة لاستخدام الكود تتم بالشكل التالي أي أن ميكروسوفت قد قامت بعكس وضعية المستطيل كما هوا واضح بالمقارنة بين الكود اعلاه والكود التالي

كود :
ControlPaint.DrawSelectionFrame(Graphics, active, insideRect, outsideRect, backColor)
يبقي السؤال هل ميكروسوفت ارتكبت خطا ما ؟ ربما هذا صحيح لكن الحقيقة إن خطأ ميكروسوفت في رأيي الشخصي أنها لا تعطي الشرح الكافي للكونترول ودائما لديهم خلل في ملفات المساعدة Help المرفقة مع الفيجوال استوديو تحديدا ولذلك نجد أن هناك الكثير والكثير من الكلاس لا يوجد لها توضيح كافي وخاصة للمبتدئين وبالتالي يتحول الامر الي علامة استفهام كبيره جدا ومن هنا قامت ميكروسوفت بابتكار MSDN وهم يقومون بتطويرها بشكل مستمر لكن للأسف مازالت نفس علامة الاستفهام موجودة حيث أن MSDN أيضا لا تعطي التوضيح الكافي للكثير من الأشياء.

أيضا هناك شئ يعتبر مفاجاه في هذا الكلاس مثلا لو حاولنا رسم بعض العناصر في الفورم مباشرة سيحدث خلل وبعض الرسومات سوف يتم رسمها مباشرة الي Desktop أي خارج حدود الفورم ولتوضيح ذلك إليكم المثال التالي
قم بفتح مشروع جديد وأضف إليه الكود التالي وانظر جيدا الي أقصي يسار الشاشة ستكتشف أن الكلاس قد قام برسم المطلوب ولكن علي Desktop مباشرة أي خارج حدود الفورم بشكل ما
لكن لو تم توظيف هذه الأوامر جيدا أي لو ربطنا بعض الأوامر بحركة الماوس داخل الفورم تحديدا فان الرسم سوف يتم داخل المكان المطلوب حيثما نريد

كود :
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)

Dim theRectangle As New Rectangle(New Point(0, 0), New Size(200, 200))
ControlPaint.DrawReversibleFrame(theRectangle, Me.BackColor, _
FrameStyle.Dashed)
Dim p1 As New Point(0, 0)
Dim p2 As New Point(150, 10)
ControlPaint.DrawReversibleLine(p1, p2, Me.BackColor)

End Sub
أيضا هناك ملحوظه أخيره أود فقط أن أوضحها للقارئ وما بهمنا هنا لنتحدث عنه هو كلمتان محددتان وهما Overloads وأيضا Overrides
الكلمة Overloads تستخدم مع Property أو Procedure معين وهي تسمح لنا بتخليق وتعريف Property معينه أو Procedure معين باستخدام نفس الاسم الموجود داخل أي كلاس ولكن بثوابت مختلفة.
الكلمة Overrides وهي ببساطه تستخدم عندما نريد أن تتخطي أو نهيمن علي شئ معين داخل الكلاس مثل Properties أو Procedures
طبعا سوف نستخدم هذان الكلمتان كثيرا طالما نحن نريد بناء كونترول لها مواصفات مختلفة أو عند إضافة مواصفات للكونترول الموجودة مع الفيجوال استوديو
عموما لكي يصل المعني اعلاه للقارئ سوف نعطي مثالا لتوضيح الامر بسرعة
مثال توضيحي علي ذلك الباتون كلاس يوجد به علي سبيل المثال لا الحصر الطرق التالية.
- OnMouseEnter
- OnMouseLeave
- OnMouseUp
- OnMouseDown
وكل طريقه تحمل صفات خاصة بها فإذا أردنا أن تتخطي أو نغير شئ معين لأحدي هذه الطرق ولكن مع الاحتفاظ بنفس الاسم فان ذلك يتم باستخدام الكود بالشكل الأتي


كود :
Protected Overloads Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
' هنا نضييف او نكتب الكود الذي نريده
MyBase.OnMouseDown(e)
End Sub
الأن وما يهمنا هنا علي وجه الخصوص هو كيف نستخدم هذا الكلاس بشكل عملي ولكي نري أهمية هذا الكلاس لذلك سوف نقوم بتصميم باتون وهو أسهل الأشياء لتوضيح خصائص هذا الكلاس
تصميم الباتون Button
بخصوص إنشاء Button الامر يتم كالأتي
أولا: نفتح مشروع جديد وليكن اسمه Control_Paint_Example_01 ثم نضيف كلاس Class بأي اسم مناسب وليكن مثلا Private Class ButtonExample وذلك يتم من قائمة Project ثم استخدام Add Class…
إذن الكود سيكون كالأتي

كود :
Private Class ButtonExample

End class
ثانيا: نضيف للكلاس باتون Button عن طريق استخدام الوراثة Inherits ثم نضيف أيضا تعريف لحالة الباتون ButtonState
فيصيح الكود كالتالي


كود :
Public Class ButtonExample

Inherits Button
Private state As ButtonState

End Class

بعد ذلك نقوم بعمل Overloads & Overrides لحركة الماوس وهي MouseUP & MouseDown وأيضا نقوم بعمل Overloads & Overrides ونقوم برسم الباتون في OnPaint فيصبح الكود بالشكل التالي


كود :
Public Class ButtonExample

Inherits Button
Private state As ButtonState

Protected Overloads Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
state = ButtonState.Pushed
MyBase.OnMouseDown(e)
End Sub

Protected Overloads Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
state = ButtonState.Normal
MyBase.OnMouseUp(e)
End Sub

Protected Overloads Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
System.Windows.Forms.ControlPaint.DrawComboButton(e.Graphics, 0, 0, Width, Height, state)
End Sub


End Class
نلاحظ أننا قد قمنا برسم الباتون في حالة OnPaint فقط وأننا قد قمنا برسم ComboButton أما في حالة MouseUp & MouseDown قمنا بتعيير حالة الباتون ButtonState فقط لا غير ألان لا يتبقي إلا أن نضيف لهذا الكلاس شئ واحد ألا وهو Sub New وذلك لكي نقوم بعمل ضبط لخاصية ٍ للكونترول SetStyle فيصبح الكود النهائي للكلاس بالشكل التالي وهنا سنلاحظ أن الكود غباره عن مجموعه من الأسطر القليلة أي أننا قد قمنا بتصميم الباتون بأسهل الطرق وبسرعة جدا

كود :
Public Class ButtonExample

Inherits Button
Private state As ButtonState

Public Sub New()
SetStyle(ControlStyles.UserPaint, True)
SetStyle(ControlStyles.DoubleBuffer, True)

SetStyle(ControlStyles.AllPaintingInWmPaint, True)
End Sub

Protected Overloads Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
state = ButtonState.Pushed
MyBase.OnMouseDown(e)
End Sub

Protected Overloads Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
state = ButtonState.Normal
MyBase.OnMouseUp(e)
End Sub

Protected Overloads Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
System.Windows.Forms.ControlPaint.DrawComboButton(e.Graphics, 0, 0, Width, Height, state)
End Sub


End Class
ألان لا يتبقي إلا إن نضيف هذا الباتون الذي قمنا بتصميمه الي الفورم لكي يعمل بشكل جيد وذلك سيتم بسهوله جدا كل ما علينا عمله أن نقوم بعمل Build للكنترول وذلك يتم من قائمة Build ثم أخر شئ لو أننا فتحنا الفورم في وضعية التصميم سنري أن الكلاس الذي قمنا بتصميمه موجود في ToolBox وكل ما علينا هو سحبه وإضافته الي الفورم ثم إضافة الكود الذي نراه مناسبا لهذا الباتون وليكن مثلا إغلاق البرنامج وذلك يتم بعمل DoubleClick علي الباتون الذي أضفناه للفورم رقم 1 وبذلك يكون الكود كالتالي

كود :
Public Class Form1


Private Sub ButtonExample1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonExample1.Click

Application.Exit()

End Sub

End Class
بالتوفيق
أخوكم عمر
}}}}
تم الشكر بواسطة:


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  صمم الكلاس الخاص بك - كلاس للتعامل مع SQL SERVER ابو ليلى 16 901 03-09-16, 07:43 PM
آخر رد: tryold
  Generic Delegates & ًWindows Forms Control - Part 2 silverlight 0 198 19-01-16, 02:01 PM
آخر رد: silverlight
  Generic Delegates & ًWindows Forms Control - Part 1 silverlight 1 257 16-01-16, 06:35 PM
آخر رد: 10468
  [درس فيديو] تشغيل اوامر Run من البرنامج & مثال غلق الويندوز بعد وقت محدد باستخدام VB.net أحمد النجار 1 543 23-12-15, 04:26 AM
آخر رد: الماجيك مسعد
  [مقال] Fun with Windows Forms & Graphics - Spy Form silverlight 1 514 23-06-15, 09:33 PM
آخر رد: silverlight
  خدمات الويندوز Windows Service RaggiTech 0 290 03-10-12, 01:46 PM
آخر رد: RaggiTech
  تفعيل خاصية RequireAdministrator لبرنامجك للتحكم بملفات الويندوز بسهولة في ويندوز 7 RaggiTech 0 378 03-10-12, 10:47 AM
آخر رد: RaggiTech
  تجزئة الكلاس أو الستركتشر على عدة ملفات RaggiTech 1 370 03-10-12, 07:32 AM
آخر رد: RaggiTech
  Threading in Windows Forms Applications RaggiTech 1 476 01-10-12, 07:36 PM
آخر رد: RaggiTech
  توضيح ادوات Ribbon Office DotNetBar for Windows Forms m.sami.ak 2 1,220 23-09-12, 01:32 PM
آخر رد: m.sami.ak

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم