كما يعلم القارئ أن جميع المبرمجين يحرصون علي أن تظهر البرامج التي يصنعونها بشكل جذاب بل ويحاولون إضفاء لمسات جمالية بطرق مختلفة حتي يجذبون المستخدم لبرامجهم لذلك ستجد الجميع يهتمون بمثل هذه الأمور حيث أنها تمثل سوقا تجاريا لابأس به وبشكل عام هذا ما سنحاول أن نوضح بعضا منه في هذا الموضوع
وكما سبق وكتبت في الجزء الأول أننا هنا لا نناقش كيف نرسم أو كيف نستخدم أوامر الرسم المختلفة بل سوف نناقش كيف نستفيد ونطور في أوامر +GDI الموجودة في الدوت نت بحيث نستفيد منها بشكل أفضل لذلك أفترض أن قارئ هذا المقال لديه المام جيد بأوامر +GDI وكيفية استخدامها
الفكرة الثانية:
الفكرة التي سوف نتحدث عنها اليوم هي كيف نرسم Ribbon أو كيف نرسم Glow
المثال الأول :
كيف يمكن أن نستفيد من الأوامر الخاصة برسم الأقواس بالإضافة الي رسم المسارات أو ما يعرف باسم GraphicsPath .......... الكود التالي يوضح كيف نرسم قوس من دائرة في داخل مستطيل
كود :
Public Class Form1
Private DarkColor As Color = Color.DarkOrange
Private LightColor As Color = Color.Orange
Private rect As New Rectangle(10, 10, 150, 150)
Private angle As Integer
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
' الغرض من رسم هذا المستطيل لكي يعمل كخلفية فقط لتوضيح كيف سيكون شكل القوس الذي نرسمه
e.Graphics.FillRectangle(Brushes.Black, Rect)
angle = 180
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddArc(Rect, angle, 180)
Using p As Pen = New Pen(DarkColor)
Using lgb As New LinearGradientBrush(Path.GetBounds(), Color.FromArgb(84, LightColor), Color.FromArgb(128, LightColor), LinearGradientMode.Vertical)
e.Graphics.FillPath(lgb, Path)
End Using
e.Graphics.DrawPath(p, Path)
End Using
End Using
End Sub
End Class
أرجو عزيزي القارئ أن تلاحظ قيمة المتغير Angle وقيمته بالمثال أعلاه تساوي صفر
حاول عزيزي القارئ أن تقوم بتغيير قيمة هذا المتغير لكي يساوي 180 أو 90 أو 270 ولاحظ الفارق في كل مرة ستجرب فيها الكود ستكتشف أن إتجاه القوس المرسوم داخل المستطيل يتغير تبعا للزاوية التي نحددها ........
المثال الثاني:
الأن لنرسم نفس القوس ولكن هذه المرة سوف نقوم بعمل Blend للألوان المستخدمة في رسم القوس وسنكرر الرسم فقط من أجل المقارنة بين مارسمناه في المثال الأول والمثال الثاني
كود :
Public Class Form1
Private DarkColor As Color = Color.DarkOrange
Private LightColor As Color = Color.Orange
Private rect As New Rectangle(10, 10, 150, 150)
Private angle As Integer
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Dim m_blend As New Blend
m_blend.Factors = New Single() {0.0F, 0.4F, 0.8F, 1.0F}
m_blend.Positions = New Single() {0.0F, 0.3F, 0.4F, 1.0F}
' الغرض من رسم هذا المستطيل هو أن يعمل كخلفية فقط لتوضيح كيف سيكون شكل القوس الذي نرسمه
e.Graphics.FillRectangle(Brushes.Black, Rect)
angle = 180
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddArc(rect, angle, 180)
Using p As Pen = New Pen(DarkColor)
Using lgb As New LinearGradientBrush(Path.GetBounds(), Color.FromArgb(84, LightColor), Color.FromArgb(128, LightColor), LinearGradientMode.Vertical)
lgb.Blend = m_blend
e.Graphics.FillPath(lgb, Path)
End Using
e.Graphics.DrawPath(p, Path)
End Using
End Using
' الغرض من رسم هذا المستطيل هو أن يعمل كخلفية فقط لتوضيح كيف سيكون شكل القوس الذي نرسمه
Dim rect1 As Rectangle = New Rectangle(Rect.X + Rect.Width + 5, Rect.Y, Rect.Width, Rect.Height)
e.Graphics.FillRectangle(Brushes.Black, rect1)
' يتم إعادة رسم هذا الجزء من أجل المقارنة فقط لا غير
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddArc(rect1, angle, 180)
Using p As Pen = New Pen(DarkColor)
Using lgb As New LinearGradientBrush(Path.GetBounds(), Color.FromArgb(84, LightColor), Color.FromArgb(128, LightColor), LinearGradientMode.Vertical)
e.Graphics.FillPath(lgb, Path)
End Using
e.Graphics.DrawPath(p, Path)
End Using
End Using
End Sub
End Class
لو نظرت جيدا الي ما رسمناه ستجدا أن هناك فارقا قد لا يبدو ظاهرا للعين لأول وهلة لكن لو ركزت عينيك علي ما رسمناه ستجد فارقا في تدرج الألوان بسبب استخدام Blend
حالو تغيير قيم Positions و Factors الخاصة بالكلاس Blend لتكتشف بنفسك اهمية هذا الكلاس في عملية التحكم في تدرج الأولوان
المثال الثالث:
سنعيد رسم المثال الثاني كما هو ولكن بدلا من أن نستخدم مستطيلا كخلفية للأقواس المرسومة سنرسم Ellipse .... جرب المثال ولاحظ الفارق
كود :
Public Class Form1
Private DarkColor As Color = Color.DarkOrange
Private LightColor As Color = Color.Orange
Private rect As New Rectangle(10, 10, 150, 150)
Private angle As Integer
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Dim m_blend As New Blend
m_blend.Factors = New Single() {0.0F, 0.4F, 0.8F, 1.0F}
m_blend.Positions = New Single() {0.0F, 0.3F, 0.4F, 1.0F}
' هنا تم رسم شكل بيضاوي بدلا من المستطيل الموجود في المثال السابق
e.Graphics.FillEllipse(Brushes.Black, rect)
angle = 180
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddArc(rect, angle, 180)
Using p As Pen = New Pen(DarkColor)
Using lgb As New LinearGradientBrush(Path.GetBounds(), Color.FromArgb(84, LightColor), Color.FromArgb(128, LightColor), LinearGradientMode.Vertical)
lgb.Blend = m_blend
e.Graphics.FillPath(lgb, Path)
End Using
e.Graphics.DrawPath(p, Path)
End Using
End Using
' يتم إعادة رسم هذا الجزء من أجل المقارنة فقط لا غير
Dim rect1 As Rectangle = New Rectangle(rect.X + rect.Width + 5, rect.Y, rect.Width, rect.Height)
' هنا تم رسم شكل بيضاوي بدلا من المستطيل الموجود في المثال السابق
e.Graphics.FillEllipse(Brushes.Black, rect1)
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddArc(rect1, angle, 180)
Using p As Pen = New Pen(DarkColor)
Using lgb As New LinearGradientBrush(Path.GetBounds(), Color.FromArgb(84, LightColor), Color.FromArgb(128, LightColor), LinearGradientMode.Vertical)
e.Graphics.FillPath(lgb, Path)
End Using
e.Graphics.DrawPath(p, Path)
End Using
End Using
End Sub
End Class
لو نظرت الي الرسم جيدا ستجد أن حواف الأقواس المرسومة بها عيوب ظاهرة للعين لذلك يفضل ان نضبط قيمة SmoothingMode ونجعل قيمتها تساوي SmoothingMode.AntiAlias
حاول أيضا عزيزي القارئ ان تقوم بتغيير الألوان المستخدمة في الرسم لكي تلاحظ الفوارق المختلفة في الأمثلة السابقة
المثال الرابع:
قد يتساءل البعض كيف نتحكم في ارتفاع القوس وهنا سنحاول ان نرسم نفس الكود أعلاه ولكن بأسلوب مختلف قليلا
كود :
Public Class Form1
Private DarkColor As Color = Color.Black
Private LightColor As Color = Color.Orange
Private rect As New Rectangle(10, 10, 150, 150)
Private startAngle As Integer
Private sweepAngle As Integer = 100
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Using path = New GraphicsPath
startAngle = ((180 - sweepAngle) / 2)
path.AddArc(rect, CSng(startAngle), CSng(sweepAngle))
Dim pt As Point = Point.Round(path.PathData.Points(0))
Using lgb = New LinearGradientBrush(New Point(Rect.Left, Rect.Bottom), New Point(Rect.Left, (pt.Y - 1)), DarkColor, Color.FromArgb(50, DarkColor))
e.Graphics.FillPath(lgb, path)
End Using
End Using
End Sub
End Class
أرجو أن تلاحظ عزيزي القارئ كيف يمكن التحكم في ارتفاع القوس عن طريق الربط بين فيمة StartAngle و SweepAngle معا حيث أن الفارق بين القيميتين يعبر عن الفارق في الإرتفاع بين النقطة التي تمثل مركز المستطيل والنقطة التي يبدأ عندها رسم القوس
أيضا أرجو أن تلاحظ كيف تم تحديد أول نقطة موجودة بالمسار GraphicsPath عن طريق تعريف متغير عبارة عن Point وكيف تم ربطها مع PathData وهو عبارة عن ReadOnly Property خاصة بالمسار وهي عبارة عن Array تحدد النقط الكلية الخاصة بشكل المسار GraphicsPath حيث باستخدامها يمكن استرجاع أول وأخر نقطة بالمسار فقط لاغير أما باق النقاط التي تمثل شكل المسار فهناك استحالة تامة لاسترجاع باق القيم الخاصة بها
المثال الخامس:
سنعيد رسم الفكرة الموجودة بالمثال السابق مع إضافة مستطيل أخر الي المسار وأرجو ان تلاحظ هنا ما سيحدث
كود :
Public Class Form1
Private DarkColor As Color = Color.Black
Private LightColor As Color = Color.Orange
Private rect As New Rectangle(10, 10, 150, 150)
Private startAngle As Integer
Private sweepAngle As Integer = 130
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Using path = New GraphicsPath
startAngle = ((180 - sweepAngle) / 2)
path.AddArc(rect, CSng(startAngle), CSng(sweepAngle))
Dim pt As Point = Point.Round(path.PathData.Points(0))
Dim r As Rectangle = rect
r.Inflate(-1, -1)
path.AddArc(r, CSng(startAngle), CSng(sweepAngle))
Using lgb = New LinearGradientBrush(New Point(rect.Left, rect.Bottom), New Point(rect.Left, (pt.Y - 1)), DarkColor, Color.FromArgb(50, DarkColor))
e.Graphics.FillPath(lgb, path)
End Using
End Using
End Sub
End Class
ستلاحظ وبالرغم من اننا نحاول أن نملأ المسار بأحد الألوان فإن ذلك لا يحدث وبدلا من ذلك يظهر لنا قوس عبارة عن جزء من محيط دائرة وبالرغم من ذلك يمكنك ان تستخدم هذا المثال في رسم إطار علي شكل قوس
أرجو أن تحاول عزيزي القارئ أن تجرب جميع الأمثلة أعلاه لكي يتضح لك مدي أهمية كلا من الأقواس Arcs و المسار GraphicsPath في طرق أو عمليات الرسم +GDI المختلفة
باق الأمثلة والأفكار سيتم عرضها بالمشاركات التالية
تقبلوا تحياتي
أخوكم عمر
في الأمثلة التالية سنحاول أن نغطي كيفية التحكم في الألوان حيث يمكن أن نجعل أي لون نختاره بأن نجعله Light أو Dark أي و ببساطة شديدة سنحاول أن نجعل اللون الذي نحدده إما غامقا أو فاتحا ومن ثم نحاول أن نستفيد من هذه الميزة في عمليات الرسم
عموما هناك أفكار كثيرة لكي نتحكم في الألوان وهي ميزة هامة جدا في عمليات +GDI المختلفة حيث أن التحكم في الألوان ودرجاتها وقيمة alpha الخاصة بها ستساعدك كثيرا عزيزى القارئ في الخروج بنتائج رائعة لكي تجعل ما ترسمه يأخذ أشكالا رائعة
المثال السادس :
تخفيف الألوان والمثال التالي يوضح ذلك
لكن عليك ان تلاحظ عزيزي القارئ اهمية استخدام هذا السطر الموجود بالكود lgb.SetSigmaBellShape(0.9)
كود :
Public Class Form1
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
' تعريف متغير يشير الي اللون الأصلي
Dim baseColor As Color = Color.Orange
Dim rect As New Rectangle(10, 10, 150, 150)
' هذه القيمة سوف تحدد الدرجة التي نحتاجها لتخفيقف اللون الأصلي
' هذه القيمة يجب أن لا تقل عن صفر ويجب أن لا تزيد عن 100
Dim percent As Integer = 80
' تحديد القيم الخاصة باللون الجديد
Dim alpha As Integer = baseColor.A
Dim red = baseColor.R + CInt(((255 - baseColor.R) / 100) * percent)
Dim green = baseColor.G + CInt(((255 - baseColor.G) / 100) * percent)
Dim blue = baseColor.B + CInt(((255 - baseColor.B) / 100) * percent)
' تعريف اللون الجديد
Dim lightColor As Color = Color.FromArgb(alpha, red, green, blue)
' رسم أي شي باستخدام اللون الأصلي واللون الجديد معا
Using lgb As New Drawing2D.LinearGradientBrush(rect, baseColor, lightColor, Drawing2D.LinearGradientMode.Vertical)
lgb.SetSigmaBellShape(0.9)
e.Graphics.FillEllipse(lgb, rect)
End Using
End Sub
End Class
المثال السابع:
تغميق الألون والمثال التالي يوضح ذلك
كود :
Public Class Form1
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
' تعريف متغير يشير الي اللون الأصلي
Dim baseColor As Color = Color.Orange
Dim rect As New Rectangle(10, 10, 150, 150)
' هذه القيمة سوف تحدد الدرجة التي نحتاجها لتغميق اللون الأصلي
' هذه القيمة يجب أن لا تقل عن صفر ويجب أن لا تزيد عن 100
Dim percent As Integer = 80
' الحصول علي لون غامق من اللون الأصلي
Dim alphaDark As Integer = baseColor.A
Dim redDark = baseColor.R - CInt(((baseColor.R) / 100) * percent)
Dim greenDark = baseColor.G - CInt(((baseColor.G) / 100) * percent)
Dim blueDark = baseColor.B - CInt(((baseColor.B) / 100) * percent)
' تعريف اللون الجديد
Dim darkColor As Color = Color.FromArgb(alphaDark, redDark, greenDark, blueDark)
' رسم أي شي باستخدام اللون الأصلي واللون الجديد معا
Using lgb As New Drawing2D.LinearGradientBrush(rect, baseColor, darkColor, Drawing2D.LinearGradientMode.Vertical)
lgb.SetSigmaBellShape(0.9)
e.Graphics.FillEllipse(lgb, rect)
End Using
End Sub
End Class
المثال الثامن:
هنا سنحاول استخدام المثال السادس والسابع لنخرج بكود مختلف قليلا وعليك عزيزي القارئ أن تلاحظ الفارق حاول أن تتحكم في قيمة المتغير الذي يؤثر علي درجة تفتيح أو تغميق اللون
كود :
Public Class Form1
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
' تعريف متغير يشير الي اللون الأصلي
Dim baseColor As Color = Color.Orange
Dim rect As New Rectangle(10, 10, 150, 150)
' هذه القيمة سوف تحدد الدرجة التي نحتاجها لتغميق اللون الأصلي
' هذه القيمة يجب أن لا تقل عن صفر ويجب أن لا تزيد عن 100
Dim percent As Integer = 20
' الحصول علي لون غامق من اللون الأصلي
Dim alphaDark As Integer = baseColor.A
Dim redDark = baseColor.R - CInt(((baseColor.R) / 100) * percent)
Dim greenDark = baseColor.G - CInt(((baseColor.G) / 100) * percent)
Dim blueDark = baseColor.B - CInt(((baseColor.B) / 100) * percent)
' تعريف اللون الجديد
Dim darkColor As Color = Color.FromArgb(alphaDark, redDark, greenDark, blueDark)
' تغيير قيمة هذا المتغير حتي نتحكم في درجة اللون الفاتح
percent = 80
' الحصول علي لون خفيف من اللون الأصلي
Dim alphaLight As Integer = baseColor.A
Dim redLight = baseColor.R + CInt(((255 - baseColor.R) / 100) * percent)
Dim greenLight = baseColor.G + CInt(((255 - baseColor.G) / 100) * percent)
Dim blueLight = baseColor.B + CInt(((255 - baseColor.B) / 100) * percent)
Dim lightColor As Color = Color.FromArgb(alphaLight, redLight, greenLight, blueLight)
' رسم أي شي باستخدام اللون الغامق واللون الفاتح معا
Using lgb As New Drawing2D.LinearGradientBrush(rect, lightColor, darkColor, Drawing2D.LinearGradientMode.Vertical)
lgb.SetSigmaBellShape(0.9)
e.Graphics.FillEllipse(lgb, rect)
End Using
End Sub
End Class
أعتقد أننا نستطيع أن نبني من الأفكار أعلاه دالتين أحدهما تستخدم في تخفيف اللون والأخري في تغميق اللون .......................... جرب وحاول بنفسك عزيز القارئ أن تبني مثل هاتين الدالتين
باق الأمثلة والأفكار سيتم عرضها بالمشاركات التالية تحت نفس الجزء وفي النهاية سنعطي مثالا كاملا لجميع الأفكار التي تحدثنا عنها
في المثال التالي سنحاول أن نخلط بين جميع الأمثلة السابقة لكي نخرج بالشكل النهائي لما نريد أن نرسمه ومن ثم نحاول ان نكتب روتين نستخدمه فيما بعد في اي مشروع
المثال التاسع:
كود :
Imports System.Drawing.Drawing2D
Public Class Form1
Private DarkColor As Color = Color.DarkOrange
Private LightColor As Color = Color.Orange
Private rect As New Rectangle(10, 10, 150, 150)
Private angle As Integer = 180
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Dim DarkColor As Color = Color.Orange
Dim LightColor As Color = Color.Yellow
Dim rect As New Rectangle(10, 10, 100, 100)
Dim WhiteColor As Color = Color.White
Dim darkRatio As Integer = 16
Dim scale As SizeF = New SizeF(CSng(rect.Width / 100), CSng(rect.Height / 100))
Dim sigmaBlend As New Blend
sigmaBlend.Factors = New Single() {0.0F, 0.4F, 0.8F, 1.0F}
sigmaBlend.Positions = New Single() {0.0F, 0.3F, 0.4F, 1.0F}
Dim darkerColor As Color = DarkColor
Dim mode As SmoothingMode = e.Graphics.SmoothingMode
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
Dim darkerColorAlpha As Integer = darkerColor.A
Dim darkerColorRed As Integer = darkerColor.R - CInt(((darkerColor.R) / 100) * darkRatio)
Dim darkerColorGreen As Integer = darkerColor.G - CInt(((darkerColor.G) / 100) * darkRatio)
Dim darkerColorBlue As Integer = darkerColor.B - CInt(((darkerColor.B) / 100) * darkRatio)
Dim glowColor As Color = Color.FromArgb(darkerColorAlpha, darkerColorRed, darkerColorGreen, darkerColorBlue)
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddEllipse(rect)
Dim pgb As New Drawing2D.PathGradientBrush(Path)
pgb.CenterPoint = New PointF(rect.Left + (rect.Width / 2), rect.Bottom + (33 * scale.Height))
pgb.CenterColor = Color.FromArgb(255, LightColor)
' Creates a gradient falloff based on a bell-shaped curve.
pgb.SetSigmaBellShape(0.85)
If darkerColor.GetBrightness >= 0.3 Then
darkerColor = glowColor
End If
pgb.SurroundColors = New Color() {Color.FromArgb(255, darkerColor)}
e.Graphics.FillEllipse(pgb, rect)
End Using
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddArc(rect, angle, angle)
Using p As Pen = New Pen(glowColor)
Using lgb As New LinearGradientBrush(Path.GetBounds(), Color.FromArgb(64, WhiteColor), Color.FromArgb(84, WhiteColor), LinearGradientMode.Vertical)
lgb.Blend = sigmaBlend
e.Graphics.FillPath(lgb, Path)
End Using
e.Graphics.DrawPath(p, Path)
End Using
End Using
Dim blender As Drawing2D.Blend = New Drawing2D.Blend()
blender.Positions = New Single() {0, 0.9, 1}
blender.Factors = New Single() {0, 1, 1}
Dim sweepRectangle As Rectangle = rect
sweepRectangle.Height -= (rect.Height / 2)
sweepRectangle.Inflate(-16 * scale.Width, -3 * scale.Height)
Using lgb As New Drawing2D.LinearGradientBrush(sweepRectangle, WhiteColor, Color.Empty, 90, True)
sweepRectangle.Height -= scale.Height / 2
lgb.Blend = blender
e.Graphics.FillEllipse(lgb, sweepRectangle)
End Using
Using borderPen As New Pen(glowColor, 2)
Dim borderRect As Rectangle = rect
e.Graphics.DrawEllipse(borderPen, borderRect)
End Using
e.Graphics.SmoothingMode = mode
End Sub
End Class
بالتأكيد يمكننا ان نرسم ما نريد أو نعدل بالكود كيفما شئنا ولكنك سوف تلاحظ عزيزي القارئ أننا لم نأتي بشئ جديد كل ما في الأمر أننا استخدمنا اوامر +GDI المختلفة والموجودة بالفعل بالدوت نت ولكن بصورة أكثر فعالية حتي نحصل علي الشكل النهائي لما نريد
وفي الكود أعلاه حاول أن تلاحظ كيفية استخدام الكلاسات Blend و LinearGradientBrush و PathGradientBrush ولاحظ أيضا كيف نتأكد من Brightness الخاصة بلون ما فإذا كانت أقل من ما نريد فإننا نقوم بتغيير اللون الي لون أخر قاتم قليلا ولكنه يأتي من نفس اللون
الكود التالي يوضح شكل الروتين النهائي الذي من الممكن ان نستخدمه في أي مشروع
بحيث نمرر له بعض المتغيرات مثل Graphics Object و Rectangle وأيضا لونين مختلفين أحدهما سيمثل اللون الغامق والأخر عبارة عن اللون الفاتح
كود :
Private Sub DrawGlowRibbon(ByVal g As Graphics, ByVal rect As Rectangle, ByVal darkColor As Color, ByVal lightColor As Color)
Dim mode As SmoothingMode = g.SmoothingMode
g.SmoothingMode = SmoothingMode.AntiAlias
Dim darkRatio As Integer = 16
Dim WhiteColor As Color = Color.White
Dim sigmaBlend As New Blend
sigmaBlend.Factors = New Single() {0.0F, 0.4F, 0.8F, 1.0F}
sigmaBlend.Positions = New Single() {0.0F, 0.3F, 0.4F, 1.0F}
Dim scale As SizeF = New SizeF(CSng(rect.Width / 100), CSng(rect.Height / 100))
Dim darkerColor As Color = darkColor
Dim darkerColorAlpha As Integer = darkerColor.A
Dim darkerColorRed As Integer = darkerColor.R - CInt(((darkerColor.R) / 100) * darkRatio)
Dim darkerColorGreen As Integer = darkerColor.G - CInt(((darkerColor.G) / 100) * darkRatio)
Dim darkerColorBlue As Integer = darkerColor.B - CInt(((darkerColor.B) / 100) * darkRatio)
Dim glowColor As Color = Color.FromArgb(darkerColorAlpha, darkerColorRed, darkerColorGreen, darkerColorBlue)
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddEllipse(rect)
Dim pgb As New Drawing2D.PathGradientBrush(Path)
pgb.CenterPoint = New PointF(rect.Left + (rect.Width / 2), rect.Bottom + (33 * scale.Height))
pgb.CenterColor = Color.FromArgb(255, lightColor)
pgb.SetSigmaBellShape(0.85)
If darkerColor.GetBrightness >= 0.3 Then
darkerColor = glowColor
End If
pgb.SurroundColors = New Color() {Color.FromArgb(255, darkerColor)}
g.FillEllipse(pgb, rect)
End Using
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddArc(rect, 180, 180)
Using p As Pen = New Pen(glowColor)
Using lgb As New LinearGradientBrush(Path.GetBounds(), Color.FromArgb(64, WhiteColor), Color.FromArgb(84, WhiteColor), LinearGradientMode.Vertical)
lgb.Blend = sigmaBlend
g.FillPath(lgb, Path)
End Using
g.DrawPath(p, Path)
End Using
End Using
Dim blender As Drawing2D.Blend = New Drawing2D.Blend()
blender.Positions = New Single() {0, 0.9, 1}
blender.Factors = New Single() {0, 1, 1}
Dim sweepRectangle As Rectangle = rect
sweepRectangle.Height -= (rect.Height / 2)
sweepRectangle.Inflate(-16 * scale.Width, -3 * scale.Height)
Using lgb As New Drawing2D.LinearGradientBrush(sweepRectangle, WhiteColor, Color.Empty, 90, True)
sweepRectangle.Height -= scale.Height / 2
lgb.Blend = blender
g.FillEllipse(lgb, sweepRectangle)
End Using
Using borderPen As New Pen(darkerColor, 2)
Dim borderRect As Rectangle = rect
g.DrawEllipse(borderPen, borderRect)
End Using
في المثال التالي سنحاول ان نبني باتون شكله لطيف وهي فكرة بسيطة جدا لكيفية استخدام الأفكار أعلاه
كود :
Imports System.Drawing.Drawing2D
Public Class RibbonButton
Inherits Control
Private DarkColor As Color
Private LightColor As Color
Private rect As Rectangle
Private Path As GraphicsPath
Private m_state As ButtonState = ButtonState.Normal
Protected Overrides ReadOnly Property DefaultSize() As System.Drawing.Size
Get
Return New Size(50, 50)
End Get
End Property
Private Sub SetGraphicsData()
Path = New GraphicsPath()
Path.AddEllipse(Me.ClientRectangle)
Dim rgn As New Region(Path)
Me.Region = rgn
rect = New Rectangle(Me.ClientRectangle.X + 1, Me.ClientRectangle.Y + 1, Me.ClientRectangle.Width - 2, Me.ClientRectangle.Height - 2)
End Sub
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
Select Case m_state
Case ButtonState.Default, ButtonState.Disabled, ButtonState.Normal
SetNormalstate()
DrawGlowRibbon(e.Graphics, rect, DarkColor, LightColor)
Exit Select
Case ButtonState.Hot
SetHoverstate()
DrawGlowRibbon(e.Graphics, rect, DarkColor, LightColor)
Exit Select
Case ButtonState.Pressed
SetPressedState()
DrawGlowRibbon(e.Graphics, rect, DarkColor, LightColor)
End Select
End Sub
Protected Overrides Sub OnMouseEnter(ByVal e As System.EventArgs)
MyBase.OnMouseEnter(e)
m_state = ButtonState.Hot
Invalidate()
End Sub
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseDown(e)
m_state = ButtonState.Pressed
Invalidate()
End Sub
Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseUp(e)
OnMouseEnter(e)
End Sub
Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseMove(e)
If (e.Button And MouseButtons.Left) = MouseButtons.Left And Not rect.Contains(e.Location) And m_state = ButtonState.Pressed Then
OnMouseLeave(e)
End If
End Sub
Protected Overrides Sub OnMouseLeave(ByVal e As System.EventArgs)
MyBase.OnMouseLeave(e)
m_state = ButtonState.Default
Invalidate()
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
Private Sub DrawGlowRibbon(ByVal g As Graphics, ByVal rect As Rectangle, ByVal darkColor As Color, ByVal lightColor As Color)
Dim mode As SmoothingMode = g.SmoothingMode
g.SmoothingMode = SmoothingMode.AntiAlias
Dim darkRatio As Integer = 16
Dim WhiteColor As Color = Color.White
Dim sigmaBlend As New Blend
sigmaBlend.Factors = New Single() {0.0F, 0.4F, 0.8F, 1.0F}
sigmaBlend.Positions = New Single() {0.0F, 0.3F, 0.4F, 1.0F}
Dim scale As SizeF = New SizeF(CSng(rect.Width / 100), CSng(rect.Height / 100))
Dim darkerColor As Color = darkColor
Dim darkerColorAlpha As Integer = darkerColor.A
Dim darkerColorRed As Integer = darkerColor.R - CInt(((darkerColor.R) / 100) * darkRatio)
Dim darkerColorGreen As Integer = darkerColor.G - CInt(((darkerColor.G) / 100) * darkRatio)
Dim darkerColorBlue As Integer = darkerColor.B - CInt(((darkerColor.B) / 100) * darkRatio)
Dim glowColor As Color = Color.FromArgb(darkerColorAlpha, darkerColorRed, darkerColorGreen, darkerColorBlue)
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddEllipse(rect)
Dim pgb As New Drawing2D.PathGradientBrush(Path)
pgb.CenterPoint = New PointF(rect.Left + (rect.Width / 2), rect.Bottom + (33 * scale.Height))
pgb.CenterColor = Color.FromArgb(255, lightColor)
pgb.SetSigmaBellShape(0.85)
If darkerColor.GetBrightness >= 0.3 Then
darkerColor = glowColor
End If
pgb.SurroundColors = New Color() {Color.FromArgb(255, darkerColor)}
g.FillEllipse(pgb, rect)
End Using
Using Path As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath()
Path.AddArc(rect, 180, 180)
Using p As Pen = New Pen(glowColor)
Using lgb As New LinearGradientBrush(Path.GetBounds(), Color.FromArgb(64, WhiteColor), Color.FromArgb(84, WhiteColor), LinearGradientMode.Vertical)
lgb.Blend = sigmaBlend
g.FillPath(lgb, Path)
End Using
g.DrawPath(p, Path)
End Using
End Using
Dim blender As Drawing2D.Blend = New Drawing2D.Blend()
blender.Positions = New Single() {0, 0.9, 1}
blender.Factors = New Single() {0, 1, 1}
Dim sweepRectangle As Rectangle = rect
sweepRectangle.Height -= (rect.Height / 2)
sweepRectangle.Inflate(-16 * scale.Width, -3 * scale.Height)
Using lgb As New Drawing2D.LinearGradientBrush(sweepRectangle, WhiteColor, Color.Empty, 90, True)
sweepRectangle.Height -= scale.Height / 2
lgb.Blend = blender
g.FillEllipse(lgb, sweepRectangle)
End Using
Using borderPen As New Pen(darkerColor, 2)
Dim borderRect As Rectangle = rect
g.DrawEllipse(borderPen, borderRect)
End Using
g.SmoothingMode = mode
End Sub
Private Sub SetNormalstate()
DarkColor = Color.Blue
LightColor = Color.Cyan
End Sub
Private Sub SetHoverstate()
DarkColor = Color.Maroon
LightColor = Color.LightYellow
End Sub
Private Sub SetPressedState()
DarkColor = Color.DarkOrange
LightColor = Color.Yellow
End Sub
#Region " Enum "
<Flags()> _
Private Enum ButtonState
Normal = &H0
Hot = &H1
Pressed = &H2
Disabled = &H4
[Default] = &H8
End Enum
#End Region
End Class
بالمرفقات ستجدون مثالا لكيفية استخدام الكلاس أعلاه وهو سيكون مثل أي باتون أخر ولكن بشكل مختلف قليلا
المثال بالمرفقات بنسخة الفيجوال استوديو 2008
أتمني ان تكون الأفكار التي تحدثنا عنها مفيدة للبعض منكم بشكل ما ...... أعتقد أنكم يمكنك تطوير الكلاس مثل رسم Text أو رسم صورة ما داخل Ribbon أو إضافة الكثير من Property له ليتناسب مع ما احتياجاتكم
أتمني أن نري إبداعاتكم المختلفة من خلال مشاركتكم اللاحقة