03-10-12, 12:50 AM
كاتب الموضوع : 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
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)
هناك شئ مهم جدا قد يربك المبرمج الذي قد يتعامل لأول مره مع هذا الكلاس حيث أن احدي الطرق الموجودة داخل هذا الكلاس وهي تحديدا DrawSelectionFrame وهذه الطريقة تستخدم بالشكل التالي
كود :
ControlPaint.DrawSelectionFrame(Graphics, active, outsideRect, insideRect, backColor)
كود :
ControlPaint.DrawSelectionFrame(Graphics, active, insideRect, outsideRect, backColor)
أيضا هناك شئ يعتبر مفاجاه في هذا الكلاس مثلا لو حاولنا رسم بعض العناصر في الفورم مباشرة سيحدث خلل وبعض الرسومات سوف يتم رسمها مباشرة الي 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 تستخدم مع 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
فيصيح الكود كالتالي
كود :
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
كود :
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
كود :
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
أخوكم عمر