05-10-12, 06:56 PM
كاتب الموضوع : silverlight
تطوير الفورم : كيفية رسم الفورم وتحريكه وتغيير أبعاده اللغة المستخدمة: الفيجوال بيسك
التطبيق: فيجوال استوديو 2005 و 2008
المستوي: التقييم متروك للقارئ
إعداد: مهندس / عمر أمين إبراهيم
السبب الرئيسي لكتابة هذا الموضوع هو سؤال لأحد الأخوة في المنتدى عن كيفية رسم الفورم باستخدام +GDI
وبالرغم أن الفورم أصلا مشتق من الكونترول وهناك مقالات كثيرة قمت بكتابتها عن تطوير الكونترول وبالطبع نفس الأفكار الموجودة تحت هذه المقالات يمكن استخدامها مع الفورم مع تعديلات قليلة جدا عموما لن أطيل عليكم ولنتحدث مباشرة عن كيفية رسم الفورم أو من الممكن أن نطلق عليه تطوير الفورم.
أفترض أن من سيقوم بتنفيذ الكود المكتوب تحت هذا المقال لدية خلفية مناسبة عن كيفية التعامل مع +GDI
أولا: لرسم الفورم نحتاج أن نقوم بتعريف بعض المستطيلات Rectangles وهذه المستطيلات نقوم برسمها باستخدام +GDI داخل الفورم وعملية الرسم تتم كلها داخل الحدث Paint الخاص بالفورم أو الأفضل أن يتم ذلك عن طريق عمل Overrides للحدث OnPaint الذي يخص الفورم ومن الممكن أن تتم عملية الرسم أيضا عن طريق عمل Overrides للحدث OnPaintBackGround و الكود التالي يعطي شكل الحدث لكل من هذه Events الأحداث
الحدث Paint يكون شكل الكود كالأتي
كود :
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
End Sub
كود :
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
End Sub
كود :
Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaintBackground(e)
End Sub
الحدث OnResize سيكون شكل الكود كالأتي
كود :
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.OnResize(e)
End Sub
كود :
Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
End Sub
الحدث WndProc سيكون شكل الكود كالأتي
كود :
<System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.LinkDemand, Flags:=System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)> _
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
MyBase.WndProc(m)
End Sub
طبعا نفتح مشروع جديد ونطلق عليه أي اسم نريد ثم نقوم بتغيير بعض Properties الصفات التي تخص الفورم في مرحلة التصميم أو مرحلة Design وهي كالأتي:
DoubleBuffered = True والهدف هنا هو تقليل Flicker أثناء عملية الرسم في الفورم بشكل عام
FormBorderSyle = None الهدف منها إلغاء Borders المعتادة
MinimumSise = (200, 200) والهدف كما تعلمون هو تحديد أقل أو أصغر أبعاد للفورم
طبعا ممكن تغيير هذه الصفات برمجيا أي بكتابتها مثلا داخل الحدث Load الخاص بالفورم
الأن لنذهب معا إلي منطقة الكود التي تخص الفورم
وسنري الكود بالشكل الأتي
كود :
Public Class Form1
End Class
تحت هذا الحدث سوف نقوم بتعريف مجموعة من المستطيلات بحيث تكون أبعادها وخصوصا العرض Width و الارتفاع Height مرتبطين بصفة موجودة بالفورم وهي ClientSize.Width وأيضا ClientSize.Height
الأن نقوم بتعريف المستطيلات ثم نقوم برسمها داخل الفورم وهنا يمكننا أن نقوك بتعريف كل مستطيل علي حده وترسمه أو كما فعلت أنا بالمثال المرفق قمت بتغطية المستطيلات بأحد الألوان طبعا نستطيع أن نفعل الكثير هنا مثلا ممكن نستخدم LinearGradientBrushes أو SolidBrush أو PathGradienBrush ونستخدمها جميعها أو بعضها في تلوين المستطيلات
أيضا قمت برسم Text في وسط الفورم باستخدام ControlPaint Class وهذا الكلاس تحدثت عنه أيضا في أحد المقالات السابقة تحت عنوان الكلاس التائه بين +GDI & System Windows Form
طبعا من يحتاج أن يعطي أو يلون أو يبدع كما يريد يمكنه استخدام نفس الأفكار الموجودة تحت سلسلة المقالات الخاصة بتطوير الكونترول أو يفعل هو ما يريد إذا كان لدية الخبرة الكافية في استخدام +GDI
علي العموم لن أركز كثيرا علي طريقة الرسم نفسها لأنه وكما قلت من يقوم بتنفيذ هذا الكود يجب أن يكون لدية معلومات مناسبة عن كيفية التعامل مع +GDI
الكود الكامل للحدث OnPaint سيكون كالأتي
كود :
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
'
' First let us Draw the Background of the form
Dim winBounds As New Rectangle(0, 0, Me.Width, Me.Height)
Using brush As New System.Drawing.Drawing2D.LinearGradientBrush(winBounds, Color.LightCoral, Color.Red, 90, True)
e.Graphics.FillRectangle(brush, winBounds)
End Using
' Let us Paint the Other Rectangles
Dim NC_Rectangles As Rectangle() = {New Rectangle(5, 5, ClientSize.Width - 10, 24), _
New Rectangle(6, 0, ClientSize.Width - 12, 5), _
New Rectangle(0, 0, 6, 6), _
New Rectangle(ClientSize.Width - 6, 0, 6, 6), _
New Rectangle(0, 6, 5, ClientSize.Height - 12), _
New Rectangle(ClientSize.Width - 5, 6, 5, ClientSize.Height - 12), _
New Rectangle(6, ClientSize.Height - 5, ClientSize.Width - 12, 5), _
New Rectangle(0, ClientSize.Height - 6, 6, 6), _
New Rectangle(ClientSize.Width - 6, ClientSize.Height - 6, 6, 6)}
Using NC_Brush As New SolidBrush(Color.FromArgb(255, Color.DarkBlue))
e.Graphics.FillRectangles(NC_Brush, NC_Rectangles)
End Using
' Draw some Text too
Dim r As Rectangle = Me.ClientRectangle
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
Dim DrawFont As New Font(Font.FontFamily, 40, FontStyle.Regular, GraphicsUnit.Pixel)
ControlPaint.DrawStringDisabled(e.Graphics, "Hello World", DrawFont, BackColor, RectangleF.op_Implicit(r), sf)
End Sub
كود :
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.OnResize(e)
Invalidate()
End Sub
ومن بعض هذه الرسائل مثلا
WM_NCHITTEST وهذه الرسالة تفسيرها Window Message Non Client Hit Test أي انها المسئولة عن ارسال ارسائل تخض Mouse Click علي الفورم وفي مناطق معينة
WM_NCMOUSEMOVE وهي عبارة عن Window Message Non Client Mouse Move وهي المسئولة عن حركة الماوس في منطقة Non Client وهي المنطقة المحددة بيمين ويسار الفورم و اسفل وأعلي الفورم والمنطقة التي بها Minimize و Maximize و Close باتون
WM_ACTIVATEAPP وهي عبارة عن Window Message Active Form وهي تقوم بتحديد حالة الفورم إذا كان Active أم لا
وهناك الكثير والكثير من الرسائل بعضها ولقد أضفت الي الملف المرفق ملف به تقريبا معظم هذه الثوابت التي تخص الفورم والكونترول المختلفة
مرحليا ما يهمنا الأن هو مجموعة من الرسائل Window Messages التي تختص بعملية تحريك الفورم Form Move وتكبير أو تصغير الفورم form Resize في مرحلة التشغيل تحديدا أو ما يطلق عليها Non Design Mode وجميعها تستخدم مع WM_NCHITTEST و هذه الرسائل تعريفها كالأتي
HTCAPTION وهي رسالة تحدد ماذا سوف يفعل الفورم عندما يتم الضغط بالماوس علي منطقة Caption وهي المنطقة التي توجد في أعلي الفورم ويتواجد بها Form.Text والأيقونة المخصصة للفورم وهي شريحة بعرض الفورم بالكامل
HTLEFT وهي تحدد حركة الماوس في يسار الفورم وهي المنطقة التي يقوم الماوس فيها بتكبير أو تصغير الفورم أفقيا من ناحية يسار الفورم
HTRIGHT وهي تحدد حركة الماوس في يمين الفورم وهي المنطقة التي يقوم الماوس فيها بتكبير أو تصغير الفورم أفقيا من ناحية يمين الفورم
HTTOP وهي منطقة رفيعة جدا فوق منطقة Caption وهي المنطقة العلوية من الفورم التي يقوم الماوس فيها بتكبير أو تصغير الفورم رأسيا من ناحية أعلي الفورم
HTBOTTOM وهي المنطقة السفلية من الفورم وفيها يقوم الماوس بتكبير الفورم رأسيا من ناحية أسفل الفورم
HTBOTTOMLEFT و HTBOTTOMRIGHT هما يعبران عن أقصي يسار ويمين الفورم من الناحية السفلية حيث يتم تصغير وتكبير الفورم بزاوية ميل 45 علي الفورم أي في الاتجاه Diagonal علي الفورم من أسفل نقطة في أقصي اليمين وأقصي اليسار
HTTOPLEFT و HTTOPRIGHT وهما يعبران عن أقصي يسار ويمين الفورم من الناحية العلوية حيث يتم تصغير وتكبير الفورم بزاوية ميل 45 علي الفورم أي في اتجاه Diagonal علي الفورم من أعلي نقطة في أقصي اليمين أو أقصي اليسار
عموما كل هذه الرسائل هي عبارة عن أرقام وتستخدم كثوابت في البرنامج وكل هذه الرسائل يمكن أن تجدها في ملف موجود في الويندوز اسمه window.h أو كما يطلق علي هذا النوع من الملفات Header Files وهي ملفات مكتوبة بلغة Pure C
الأن وقبل أن نقوم بعمل Overrides الي الحدث WndProc سنقوم بإضافة مجموعة من الثوابت الي الفورم كود وكل هذه الثوابت سوف نستخدمها في التعامل مع الفورم وهذه الثوابت ممكن إضافتها علي سبيل المثال كأنها Public Constants أو Friend Constantsوهذه الثوابت سيتم إضافتها الي في أول الفورم كالأتي
كود :
#Region "Constants"
' Define Hit Test Constants refer to "windows.h" header file
' Non Client Area Hit Test
Friend Const WM_NCHITTEST As Integer = &H84
' Hit Test in Caption Rectangle
Friend Const HTCAPTION As Integer = &H2
' Hit Test in Left Rectangle
Friend Const HTLEFT As Integer = &HA
' Hit Test in Right Rectangle
Friend Const HTRIGHT As Integer = &HB
' Hit Test in Top Rectangle
Friend Const HTTOP As Integer = &HC
' Hit Test in Top Left Rectangle
Friend Const HTTOPLEFT As Integer = &HD
' Hit Test in Top Right Rectangle
Friend Const HTTOPRIGHT As Integer = &HE
' Hit Test in Bottom Rectangle
Friend Const HTBOTTOM As Integer = &HF
' Hit Test in Bottom Left Rectangle
Friend Const HTBOTTOMLEFT As Integer = &H10
' Hit Test in Bottom right Rectangle
Friend Const HTBOTTOMRIGHT As Integer = &H11
#End Region