مقال: أفكار في الجرافكس ....... الجزء الثاني Graphics Ideas in VisualBasic.Net Part 2
في الكود الخاص بالمثال الثالث الي الخامس في الجزء الأول يوجد بعض القصور وهي كالتالي
1- إهتزاز الرسم أثناء عملية تحريك المستطيل
2- عند الضغط علي الفورم في اي ماكن بالمثال الثالث يتم تحريك المستطيل
3- عند الضغط علي الفورم في يمين أو يسار المستطيل بالمثال الرابع يتم تحريك المستطيل
4- عند الضغط علي الفورم في أعلي أو أسفل المستطيل بالمثال الخامس يتم تحريك المستطيل
5- عند تحريك المستطيل خارج أبعاد الفورم يبدأ المستطيل في الاختفاء
1- إهتزاز الرسم أثناء عملية تحريك المستطيل
2- عند الضغط علي الفورم في اي ماكن بالمثال الثالث يتم تحريك المستطيل
3- عند الضغط علي الفورم في يمين أو يسار المستطيل بالمثال الرابع يتم تحريك المستطيل
4- عند الضغط علي الفورم في أعلي أو أسفل المستطيل بالمثال الخامس يتم تحريك المستطيل
5- عند تحريك المستطيل خارج أبعاد الفورم يبدأ المستطيل في الاختفاء
ملحوظة:
حاول عزيزي القارئ أن تجد حلولا لمثل هذه المشاكل وحاول أيضا أن تستخدم شكلا هندسيا أخر غير المستطيل ..... وذلك قبل أن تقرأ باقي الموضوع
ألا يذكرك الكود الموجود أعلاه بأي كونترول تستخدمه علي سبيل المثال TrackBar أو ScrollBar وهذا يعود بنا إلي بداية الموضوع وهو أن مجموعة أفكار صغيرة سوف تؤدي الي بناء فكرة كبيرة
في الكود الذي
استخدمناه في المثال الثالث الي الخامس الأول كان
هناك بعض القصور وفي الأمثلة التالية سوف نحاول التخلص من هذا القصور في الكود
لكي نتخلص من Flicker أو من الإهتزازات
التي نراها أثناء عملية تحريك الشكل الهندسي علينا أن نقوم إما بضبط خاصية
DoubleBuffered بحيث نجعل
قيمتها تساوي True
وهذا يحدث في مرحلة
DesignTime أو من الممكن أن نغير القيمة برمجيا
حل أخر وهو أن نستخدم SetStyle لضبط القيم التي تؤثر علي DoubleBuffering والكود التالي يوضح كيفية عمل ذلك
حل أخر وهو أن نستخدم SetStyle لضبط القيم التي تؤثر علي DoubleBuffering والكود التالي يوضح كيفية عمل ذلك
Public Sub New()
InitializeComponent()
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.UserPaint, True)
End Sub
المثال السادس: لكي نتخلص من أوجه القصور الموجودة بالمثال الرابع أعلاه يجب علينا أن نعيد صياغة المتغيرات قليلا بحيث تتناسب مع احتتياجات الفكرة التي نتحدث عنها وبالتالي سوف نحتاج الي اضافة متغيرات جديدة وبشكل مختلف قليلا وهذه المتغيرات كالتالي: تعريف متغير يشير الي الشكل المراد تحريكه وهو عبارة عن Rectangle تعريف متغير يشير الي عرض هذه المستطيل وهو عبارة عن Integer تعريف متغير يشير الي ارتفاع المستطيل وهو عبارة عن Integer تعريف متغير يشير الي أقصي مسافة يمكن أن يتحركها المستطيل وهو عبارة عن Integer تعريف متغير يشير الي أقل مسافة يمكن أن يتحركها المستطيل وهو عبارة عن Integer تعريف متغير يشير الي نصف ارتفاع المستطيل وهو سيكون عبارة عن Integer تعريف متغير يشير الي الفارق بين أقصي مسافة يستطيع أن يتحركها المستطيل مطروحا منها عرض المستطيل وهو سيكون عبارة عن Integer تعريف متغير يشير الي أن الماوس موجود بالفعل داخل المستطيل وهو سيكون عبارة عن Boolean تعريف متغير يشير الي أن الماوس علي يمين المستطيل وهو سيكون عبارة عن Boolean تعريف متغير يشير يشير الي أن الماوس علي يمين المستطيل وهو سيكون عبارة عن Boolean والكود التالي يوضح شكل هذه المتغيرات
Public Class Form1
Private rect As Rectangle
Private IsMouseInRectLeft As Boolean = False
Private IsMouseInRectRight As Boolean = False
Private IsMouseInsideRect As Boolean = False
Private rectWidth As Integer = 22
Private rectHeight As Integer = 22
Private maximumHorizontal As Integer = 0
Private minimumHorizontal As Integer = 0
Private x As Integer = 0
Private MiddleOfRectWidth As Integer = 0
End Class
الكود التالي يوضح كيفية ربط المتغيرات التي تم تعريفها وإعطاؤها قيما أولية لكي تتم عملية رسم المستطيل بشكل سليم
Private Sub SetGraphicsData()
rect = New Rectangle(Me.ClientRectangle.X, Me.ClientRectangle.Y, rectWidth, rectHeight)
MiddleOfRectWidth = rectWidth / 2
maximumHorizontal = Me.ClientRectangle.Right
minimumHorizontal = Me.ClientRectangle.X
x = maximumHorizontal - rectWidth
End Sub
نضبط Flicker أو الاهتزازات الناتجة عن تحريك المستطيل كما سبق وأوضحنا في المشاركة السابقة وأيضا نمرر القيم الأولية لكي تحدث عملية الرسم بشكل صحيح والكود التالي يوضح ذلك
Public Sub New()
InitializeComponent()
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.UserPaint, True)
SetGraphicsData()
End Sub
نعيد صياغة الكود الخاص بأحداث الماوس وهي MouseDown و MouseUp و MouseMove بحيث نربط
المتغيرات التي قمنا بتعريفها مع القيم الخاصة بمكان
الماوس علي الفورم والكود يوضح ذلك
Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
MyBase.OnMouseDown(e)
If rect.Contains(e.Location) Then
IsMouseInsideRect = True
MiddleOfRectWidth = e.Location.X - rect.X
Else
If e.Location.X < Me.rect.X Then
IsMouseInRectLeft = True
Else
IsMouseInRectRight = True
End If
End If
Invalidate()
End Sub
Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
MyBase.OnMouseUp(e)
If IsMouseInsideRect Then
IsMouseInsideRect = False
If e.Location.X > minimumHorizontal + MiddleOfRectWidth And _
e.Location.X < x + MiddleOfRectWidth Then
rect.X = e.Location.X - MiddleOfRectWidth
IsMouseInsideRect = False
End If
ElseIf IsMouseInRectLeft Then
IsMouseInRectLeft = False
ElseIf IsMouseInRectRight Then
IsMouseInRectRight = False
End If
Invalidate()
End Sub
Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
MyBase.OnMouseMove(e)
If IsMouseInsideRect Then
If e.Location.X <= minimumHorizontal + MiddleOfRectWidth Then
rect.X = minimumHorizontal
ElseIf e.Location.X >= x + MiddleOfRectWidth Then
rect.X = x
Else
rect.X = e.Location.X - MiddleOfRectWidth
End If
Invalidate()
End If
End Sub
الأن لنرسم المستطيل علي الفورم من خلالا الحدث Paint ويمكن هنا أن نقوم برسم اي شئ
نريده بشرط أن نرسمه قبل أن نرسم المستطيل المراد تحريكه وهنا قمت برسم
مستطيل سيعمل كخلفة للمستطيل المراد تحريكه والكود التالي يوضح ذلك
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
Dim backRectangle As New Rectangle(Me.ClientRectangle.X, Me.ClientRectangle.Y, Me.Width, rect.Height)
Using lgbBack As New Drawing2D.LinearGradientBrush(backRectangle, Color.Orange, Color.Yellow, 90, True)
e.Graphics.FillRectangle(lgbBack, backRectangle)
End Using
Using lgb As New Drawing2D.LinearGradientBrush(rect, Color.FromArgb(255, Color.Cyan), Color.FromArgb(255, Color.DarkBlue), Drawing2D.LinearGradientMode.Vertical)
e.Graphics.FillRectangle(lgb, rect)
e.Graphics.DrawRectangle(New Pen(Color.DarkBlue, 1.5F), rect)
End Using
End Sub
أخر شئ يجب علينا أن نفعله هو أن نتأكد دائما أن
عملية رسم المستطيل ستتم بشكل جيد وذلك عندما تتغير ابعاد الفورم أو الكونترول والحدثان المسئولان
عن ذلك هما الحدث OnResize وأيضا الحدث
OnSizeChanged والكود التالي يوضح
ذلك
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.OnResize(e)
SetGraphicsData()
Invalidate()
End Sub
Protected Overrides Sub OnSizeChanged(ByVal e As EventArgs)
MyBase.OnSizeChanged(e)
SetGraphicsData()
End Sub
الكود التالي يوضح الكود النهائي والخاص بكيفية
تحريك المستطيل في الاتجاه الأفقي
' Horizontal Movement
Public Class Form1
Private rect As Rectangle
Private IsMouseInRectLeft As Boolean = False
Private IsMouseInRectRight As Boolean = False
Private IsMouseInsideRect As Boolean = False
Private rectWidth As Integer = 22
Private rectHeight As Integer = 22
Private maximumHorizontal As Integer = 0
Private minimumHorizontal As Integer = 0
Private x As Integer = 0
Private MiddleOfRectWidth As Integer = 0
Public Sub New()
InitializeComponent()
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.UserPaint, True)
SetGraphicsData()
End Sub
Private Sub SetGraphicsData()
rect = New Rectangle(Me.ClientRectangle.X, Me.ClientRectangle.Y, rectWidth, rectHeight)
MiddleOfRectWidth = rectWidth / 2
maximumHorizontal = Me.ClientRectangle.Right
minimumHorizontal = Me.ClientRectangle.X
x = maximumHorizontal - rectWidth
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
Dim backRectangle As New Rectangle(Me.ClientRectangle.X, Me.ClientRectangle.Y, Me.Width, rect.Height)
Using lgbBack As New Drawing2D.LinearGradientBrush(backRectangle, Color.Orange, Color.Yellow, 90, True)
e.Graphics.FillRectangle(lgbBack, backRectangle)
End Using
Using lgb As New Drawing2D.LinearGradientBrush(rect, Color.FromArgb(255, Color.Cyan), Color.FromArgb(255, Color.DarkBlue), Drawing2D.LinearGradientMode.Vertical)
e.Graphics.FillRectangle(lgb, rect)
e.Graphics.DrawRectangle(New Pen(Color.DarkBlue, 1.5F), rect)
End Using
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
MyBase.OnMouseDown(e)
If rect.Contains(e.Location) Then
IsMouseInsideRect = True
MiddleOfRectWidth = e.Location.X - rect.X
Else
If e.Location.X < Me.rect.X Then
IsMouseInRectLeft = True
Else
IsMouseInRectRight = True
End If
End If
Invalidate()
End Sub
Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
MyBase.OnMouseUp(e)
If IsMouseInsideRect Then
IsMouseInsideRect = False
If e.Location.X > minimumHorizontal + MiddleOfRectWidth And _
e.Location.X < x + MiddleOfRectWidth Then
rect.X = e.Location.X - MiddleOfRectWidth
IsMouseInsideRect = False
End If
ElseIf IsMouseInRectLeft Then
IsMouseInRectLeft = False
ElseIf IsMouseInRectRight Then
IsMouseInRectRight = False
End If
Invalidate()
End Sub
Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
MyBase.OnMouseMove(e)
If IsMouseInsideRect Then
If e.Location.X <= minimumHorizontal + MiddleOfRectWidth Then
rect.X = minimumHorizontal
ElseIf e.Location.X >= x + MiddleOfRectWidth Then
rect.X = x
Else
rect.X = e.Location.X - MiddleOfRectWidth
End If
Invalidate()
End If
End Sub
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.OnResize(e)
SetGraphicsData()
Invalidate()
End Sub
Protected Overrides Sub OnSizeChanged(ByVal e As EventArgs)
MyBase.OnSizeChanged(e)
SetGraphicsData()
End Sub
End Class
المثال السابع:
تحريك المستطل في الاتجاه الراسي فقط - الكود والمتغيرات لا تختلف كثيرا عن الكود الخاص بتحريك الفورم في الاتجاه الأفقي والموجودة بالمثال السادس أعلاه .... عليك عزيزي القارئ أن تلاحظ الفارق فقط في ربط المتغيرات مع حركة الماوس الراسية في أحداث الماوس أو كيفية الرسم في الاتجاه الأفقي أو كيفية ربط أبعاد المستطيل المراد تحريكه مع أبعاد الفورم والكود النهائي لكيفية تحريك المستطيل في الاتجاه الراسي كالتالي
تحريك المستطل في الاتجاه الراسي فقط - الكود والمتغيرات لا تختلف كثيرا عن الكود الخاص بتحريك الفورم في الاتجاه الأفقي والموجودة بالمثال السادس أعلاه .... عليك عزيزي القارئ أن تلاحظ الفارق فقط في ربط المتغيرات مع حركة الماوس الراسية في أحداث الماوس أو كيفية الرسم في الاتجاه الأفقي أو كيفية ربط أبعاد المستطيل المراد تحريكه مع أبعاد الفورم والكود النهائي لكيفية تحريك المستطيل في الاتجاه الراسي كالتالي
' Vertical Movement
Public Class Form3
Private rect As Rectangle
Private rectWidth As Integer = 22
Private rectHeight As Integer = 22
Private y As Integer = 0
Private MiddleOfRectHeight As Integer = 0
Private maximumVertical As Integer = 0
Private minimumVertical As Integer = 0
Private IsMouseAboveRectangle As Boolean = False
Private IsMouseUnderRectangle As Boolean = False
Private IsMouseInsideRect As Boolean = False
Public Sub New()
InitializeComponent()
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.UserPaint, True)
SetGraphicsData()
End Sub
Private Sub SetGraphicsData()
rect = New Rectangle(Me.ClientRectangle.X, Me.ClientRectangle.Y, rectWidth, rectHeight)
MiddleOfRectHeight = rectHeight / 2
maximumVertical = Me.ClientRectangle.Bottom
minimumVertical = Me.ClientRectangle.Y
y = maximumVertical - rectHeight
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
Dim backRectangle As New Rectangle(Me.ClientRectangle.X, Me.ClientRectangle.Y, rect.Width, Me.Height)
Using lgbBack As New Drawing2D.LinearGradientBrush(backRectangle, Color.Orange, Color.Yellow, 180, True)
e.Graphics.FillRectangle(lgbBack, backRectangle)
End Using
Using lgb As New Drawing2D.LinearGradientBrush(rect, Color.FromArgb(255, Color.Cyan), Color.FromArgb(255, Color.DarkBlue), Drawing2D.LinearGradientMode.Horizontal)
e.Graphics.FillRectangle(lgb, rect)
e.Graphics.DrawRectangle(New Pen(Color.DarkBlue, 1.5F), rect)
End Using
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
MyBase.OnMouseDown(e)
If rect.Contains(e.Location) Then
IsMouseInsideRect = True
MiddleOfRectHeight = e.Location.Y - rect.Y
Else
If e.Location.Y < Me.rect.Y Then
IsMouseAboveRectangle = True
Else
IsMouseUnderRectangle = True
End If
End If
Invalidate()
End Sub
Protected Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
MyBase.OnMouseUp(e)
If IsMouseInsideRect Then
IsMouseInsideRect = False
If e.Location.Y > minimumVertical + MiddleOfRectHeight And _
e.Location.Y < y + MiddleOfRectHeight Then
rect.Y = e.Location.Y - MiddleOfRectHeight
IsMouseInsideRect = False
End If
ElseIf IsMouseAboveRectangle Then
IsMouseAboveRectangle = False
ElseIf IsMouseUnderRectangle Then
IsMouseUnderRectangle = False
End If
Invalidate()
End Sub
Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
MyBase.OnMouseMove(e)
If IsMouseInsideRect Then
If e.Location.Y <= minimumVertical + MiddleOfRectHeight Then
rect.Y = minimumVertical
ElseIf e.Location.Y >= y + MiddleOfRectHeight Then
rect.Y = y
Else
rect.Y = e.Location.Y - MiddleOfRectHeight
End If
Invalidate()
End If
End Sub
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.OnResize(e)
SetGraphicsData()
Invalidate()
End Sub
Protected Overrides Sub OnSizeChanged(ByVal e As EventArgs)
MyBase.OnSizeChanged(e)
SetGraphicsData()
End Sub
End Class
Comments
Post a Comment