مقال: أفكار في الجرافكس ....... الجزء الثاني Graphics Ideas in VisualBasic.Net Part 2



في الكود الخاص بالمثال الثالث الي الخامس في الجزء الأول يوجد بعض القصور وهي كالتالي

1-
إهتزاز الرسم أثناء عملية تحريك المستطيل
2-
عند الضغط علي الفورم في اي ماكن بالمثال الثالث يتم تحريك المستطيل
3-
عند الضغط علي الفورم في يمين أو يسار المستطيل بالمثال الرابع يتم تحريك المستطيل
4-
عند الضغط علي الفورم في أعلي أو أسفل المستطيل بالمثال الخامس يتم تحريك المستطيل
5-
عند تحريك المستطيل خارج أبعاد الفورم يبدأ المستطيل في الاختفاء

ملحوظة:

حاول عزيزي القارئ أن تجد حلولا لمثل هذه المشاكل وحاول أيضا أن تستخدم شكلا هندسيا أخر غير المستطيل ..... وذلك قبل أن تقرأ باقي الموضوع
ألا يذكرك الكود الموجود أعلاه بأي كونترول تستخدمه علي سبيل المثال TrackBar أو ScrollBar وهذا يعود بنا إلي بداية الموضوع وهو أن مجموعة أفكار صغيرة سوف تؤدي الي بناء فكرة كبيرة


في الكود الذي استخدمناه في المثال الثالث الي الخامس الأول كان هناك بعض القصور وفي الأمثلة التالية سوف نحاول التخلص من هذا القصور في الكود

 لكي نتخلص من Flicker أو من الإهتزازات التي نراها أثناء عملية تحريك الشكل الهندسي علينا أن نقوم إما بضبط خاصية DoubleBuffered بحيث نجعل قيمتها تساوي True وهذا يحدث في مرحلة DesignTime أو من الممكن أن نغير القيمة برمجيا

حل أخر وهو أن نستخدم 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

Popular posts from this blog

مقدمة الي تشفير الحروف الأبجدية العربية

VB.NET Translucent Control using GDI+

Add Custom Event to a Class in VB.NET