الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

كيفية تطوير أداة Splitbutton

بدأه محمد رضى في 9 أكتوبر 2009 · 0 رد · 1,045 مشاهدة · في Microsoft Visual Basic.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1

السلام عليكم و رحمة الله تعالى و بركاته...

أحد مربعات التحكم التي بدأنا نراها على واجهات المستخدم بعد صدور ويندوز فيستا هي Split Button. هذا الزر ذي الخصائص المتعددة, إضافة إلى لعبه دور الزر العادي Button, تمت زيادة سهم على يمينه تمكن المبرمج من إضافة لائحة من الخيارات الإضافية إلى جانب العمل الرئيس لمربع الزر العادي. السهم الموجود على يمين الزر Split Button يلعب نفس الدور الذي يلعبه الزر الصغير الموجود إلى يمين مربع اللائحة المدمجة Combo Box. المستخدم يمكن أن يضغط على الزر لتنفيذ العمل الافتراضي للزر, كما يمكن له أن يضغط على السهم يمين الزر لإظهار باقي الخيارات التي يوفرها البرنامج. كمثال على الزر Split Button, مربع الحوار Open file للبرنامج Visual Studio الذي يمكن المستخدم من فتح الملف المختار على المحرر الافتراضي له حسب امتداد اسم الملف, أو النقر على السهم يمين الزر Open و اختيار Open with… على قائمة السياق التي تظهر لاختيار محرر مشخص للملف المختار.

post-207152-1255086135_thumb.jpg

الأداة SplitButton التي سنتكلم عنها في هذا الموضوع ترث كل وظائف الأداة Button كما سنقوم بزيادة ما يلي :

DropDownContextMenu : خاصية من نوع ContextMenuStrip تحدد أو ترجع قائمة السياق التي ستظهر عند النقر على السهم يمين الزر SplitButton.

DropDown : حدث يحدث عند النقر على السهم يمين الزر SplitButton قبيل ظهور قائمة السياق إذا كانت محددة على الخاصية DropDownContextMenu.

SetDropDown : دالة تمكن من تحديد حالة السهم يمين الزر. 1 تظهر السهم في وضع مضغوط و 0 تظهره في وضع عادي.

دعونا الآن نستعرض الكود وراء الزر SplitButton. كما هي العادة, سنحتاج إلى التعامل مع Windows API لتشغيل الأداة بالطريقة العادية. و هذه لائحة بالتعاريف التي سنحتاجها :

	  ' معرف نمط ويندوز فيستا للزر
	  Private Const BS_SPLITBUTTON As Integer = &HC
	  Private Const BCM_FIRST As Integer = &H1600
	  ' لتحديد حالة الزر
	  Private Const BCM_SETDROPDOWNSTATE As Integer = BCM_FIRST + &H6
	  ' رسالة ويندوز عند ضغط الزر الأيسر للفأرة
	  Private Const WM_LBUTTONDOWN As Int32 = &H201
	  ' رسالة ويندوز عند إفلات الزر الأيسر للفأرة
	  Private Const WM_LBUTTONUP As Int32 = &H202
	  ' رسالة ويندوز عند ضرورة رسم مربع الزر
	  Private Const WM_PAINT As Int32 = &HF
	  ' رسالة ويندوز عند إلغاء نشاط الزر
	  Private Const WM_KILLFOCUS As Int32 = &H8


	  ' دالة إرسال رسائل ويندوز بنمط نص
	  <DllImport("user32.dll", CharSet:=CharSet.Unicode)> _
	  Private Shared Function SendMessage(ByVal hWnd As HandleRef, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
	  End Function

بعد تحديد التعريفات, سنحتاج إلى متغيرات لتحديد الحالة الحالية لمؤشر الفأرة و حالة السهم يمين الزر SplitButton :

	  ' لحفظ حالة الزر الأيسر للفأرة
	  Private IsMouseDown As Boolean = False
	  ' لحفظ حالة مربع الزر
	  Private IsDownState As Boolean = False

لإظهار الزر العادي Button بنمط الزر SplitButton, نحتاج إلى إخبار إطار الدوت نت أن نظام التشغيل هو من سيتكلف بعملية رسم الزر.

	  Public Sub New()
		  ' ضروري لإضهار صيغة ويندوز فيستا على الزر
		  Me.FlatStyle = Windows.Forms.FlatStyle.System
	  End Sub

إضافة إلى تحديد الخاصية FlatStyle, نحتاج كذلك إلى تغيير نمط إنشاء الزر Button لتحويله إلى زر من نوع SplitButton. نقوم بتغيير طريقة عمل الخاصية CreateParams كي ترجع النمط الجديد الذي نريده للزر :

	  ' تتم قراءة هذه الخاصية عند إنشاء مربع الزر
	  Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
		  Get
			  ' تعديل في بارامترز الإنشاء لتفعيل إضهار الزر بصيغة ويندوز فيستا
			  Dim cp As CreateParams = MyBase.CreateParams
			  cp.Style = cp.Style Or BS_SPLITBUTTON
			  Return cp
		  End Get
	  End Property

للتحكم في حالة السهم يمين الزر SplitButton, سنحتاج إلى دالة خاصة ترسل رسالة BCM_SETDROPDOWNSTATE لمربع الزر لتحديد حالة السهم :

	  ' هذه الدالة ترسل رسالة لمربع الزر لتحديد حالته
	  ' state : واحد تحدد حالة الزر في : السهم على يمين الزر مضغوط, صفر : غير مضغوط
	  Private Sub InternalSetDropDown(ByVal state As Integer)
		  SendMessage(New HandleRef(Me, Me.Handle), BCM_SETDROPDOWNSTATE, New IntPtr(state), IntPtr.Zero)
	  End Sub

الدالة أعلاه معدة للاستعمال الداخلي للأداة و لكن قد يحتاج المبرمج لتحديد أو تشخيص حالة السهم, لهذا قمت بزيادة الدالة :

	  Public Sub SetDropDown(ByVal down As Boolean)
		  IsMouseDown = down
		  IsDownState = down
		  InternalSetDropDown(IIf(down, 1, 0))
	  End Sub

لدعم الإظهار الأوتوماتيكي للوائح المنسدلة تمت زيادة الخاصية DropDownContextMenu التي تمكن من تحديد ContextMenuStrip الذي سيظهر عند النقر على السهم يمين الزر :

	  Private WithEvents _DropDownContextMenu As ContextMenuStrip
	  <Description("يحدد أو يرجع اللائحة المنسدلة التي تظهر عند النقر على السهم يمين الزر")> _
	  Public Property DropDownContextMenu() As ContextMenuStrip
		  Get
			  Return _DropDownContextMenu
		  End Get
		  Set(ByVal value As ContextMenuStrip)
			  _DropDownContextMenu = value
			  ' تسجيل في الحدثين فتح و غلق اللائحة المنسدلة حتى نتمكن من تحديد الحالة المثالية لمربع الزر
			  If Not value Is Nothing Then
				  AddHandler _DropDownContextMenu.Opened, AddressOf _DropDownContextMenu_Opened
				  AddHandler _DropDownContextMenu.Closed, AddressOf _DropDownContextMenu_Closed
			  End If
		  End Set
	  End Property

ستلاحظون معي أنه بمجرد تحديد الخاصية DropDownContextMenu يتم حجز اشتراك في الحدثين Opened و Closed لـ ContextMenuStrip. هذا لمحاكاة التصرف الطبيعي للزر SplitButton حيث أن السهم يبقى في حالة ضغط حتى تختفي قائمة السياق.

أخيرا, سنحتاج إلى التقاط رسائل ويندوز الموجهة إلى الزر SplitButton للتحكم المباشر في حالته لمحاكاة التصرف الطبيعي له كما يظهر على البرامج المثبتة مع نظام التشغيل و البرامج التجارية. التقاط رسائل ويندوز الموجهة إلى مربع تحكم تتم عبر الدالة WndProc التي تعتبر القلب النابض لكل فئة لها تمثيل ظاهري على واجهة المستخدم.

	  ' تتم المناداة على هذه الدالة في كل مرة تم استقبال رسالة ويندوز مرسولة نحو مربع الزر
	  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
		  Select Case m.Msg
			  Case BCM_SETDROPDOWNSTATE ' عند تغيير حالة مربع الزر
				  If m.HWnd = Handle Then
					  If m.WParam.ToString() = "1" Then ' حالة الزر : المستخدم ضغط على السهم يمين الزر
						  If Not IsDownState Then ' إذا لم يكن مضغوطا
							  IsDownState = True ' حفظ حالة السهم يمين الزر في مضغوط
							  ' إعلام البرنامج بالحدث
							  RaiseEvent DropDown(Me, EventArgs.Empty)
							  ' إذا تم تحديد لائحة منسدلة
							  If Not _DropDownContextMenu Is Nothing Then
								  ' إضهار اللائحة المنسدلة
								  _DropDownContextMenu.Show(Me, 0, Height)
							  End If
						  End If
					  End If
				  End If
				  ' لمزيد من التأكيد
				  If IsMouseDown Then
					  ' تحديد حالة مربع الزر في : السهم يمين الزر مضغوط
					  IsDownState = True
				  End If
			  Case WM_LBUTTONDOWN ' عند الضغط على الزر الأيسر للفأرة
				  ' حفظ الحدث
				  IsMouseDown = True
			  Case WM_LBUTTONUP ' عند إفلات الزر الأيسر للفأرة
				  If IsDownState Then
					  If _DropDownContextMenu Is Nothing Then
						  ' تحديد حالة الزر في : السهم يمين الزر غير مضغوط
						  IsMouseDown = False
						  IsDownState = False
						  InternalSetDropDown(0)
					  End If
				  End If
			  Case WM_KILLFOCUS ' عند إلغاء نشاط مربع الزر
				  If IsDownState Then
					  ' تحديد حالة الزر في : السهم يمين الزر غير مضغوط
					  IsMouseDown = False
					  IsDownState = False
					  InternalSetDropDown(0)
				  End If
			  Case WM_PAINT
				  ' رسم الزر في الحالة الحالية له
				  If IsDownState Then InternalSetDropDown(1)
		  End Select
		  MyBase.WndProc(m)
	  End Sub

سنلتقط الرسالة BCM_SETDROPDOWNSTATE التي تعلمنا بتغيير في حالة السهم يمين الزر التي تمرر عبر الوسيط m.WParam حيث إذا كان 1 فالمستخدم قد قام بالنقر على السهم أما 0 فالسهم يمين الزر يحتاج لكي يظهر في الوضع العادي الغير مضغوط. عند الرسالة WM_LBUTTONDOWN سنحفظ حالة الزر الأيسر للفأرة في مضغوط حتى يتم تغيير حالة السهم يمين الزر عند وصول الرسالة BCM_SETDROPDOWNSTATE. عند الرسائل WM_KILLFOCUS و WM_LBUTTONUP نقوم بحفظ حالة الزر الأيسر للفأرة في غير مضغوط حتى يتم تغيير حالة السهم يمين الزر عند وصول الرسالة BCM_SETDROPDOWNSTATE. نقوم بحفظ حالة الزر الأيسر للفأرة لأنه في حالة النقر على السهم يمين الزر SplitButton يقوم نظام التشغيل أو مسير واجهة المستخدم بإرسال الرسالة BCM_SETDROPDOWNSTATE إلى المربع المعني بالأمر حتى يقوم باللازم. و أخيرا سنقوم برسم الحالة الحالية للسهم يمين الزر عند وصول الرسالة WM_PAINT حسب قيم المتغيرين IsMouseDown و IsDownState.

الحدث DropDown الذي تمت زيادته للأداة SplitButton نقوم بالمناداة عليه عند النقر على السهم يمين الزر قبيل إظهار اللائحة المنسدلة عند وصول الرسالة BCM_SETDROPDOWNSTATE عندما يقرر الكود وجوب تغيير حالة السهم إلى الوضع المضغوط.

في الملف المرفق, ستجدون مشروعا صغير يبين خصائص الأداة SplitButton به الكود الكامل معلق عليه بالتفصيل إضافة إلى كود التطرق لحالة إظهار لائحة مشخصة و التحكم في حالة السهم يمين الزر بطريقة مشخصة.

تحياتي...

VistaSplitButton.rar

تم تعديل هذه المشاركة بواسطة محمد رضى في 9 أكتوبر 2009 في 14:17

مواضيع مشابهة