مشاركة عبر


الإرشادات التفصيلية: قم بإنشاء عنصر تحكم Windows Forms التي يأخذ ميزة من ‏‫Visual Studio التصميم-الوقت ميزات

تجربة وقت التصميم عنصر تحكم مخصص يمكن تحسينه بتأليف مصمم مخصصة مقترنة.

توضح هذه معاينة كيفية إنشاء مخصص مصمم المخصص عنصر تحكم. سيتم تطبيق MarqueeControlالنوع ومصمم مقترن فئة، يدعى MarqueeControlRootDesigner.

MarqueeControlنوع تطبيق عرض مشابه للشاشة اﻻسﻻمية خاصة بمسرح، مع الأضواء المتحركة و وميض. نص

مصمم لهذا عنصر تحكم يتفاعل مع بيئة التصميم لتوفير خبرة مخصصة لوقت التصميم. بواسطة مصمم مخصصة، يمكنك تجميع مخصص MarqueeControlالتنفيذ مع الأضواء المتحركة و يومض نص في العديد من تركيبات. يمكنك استخدام عنصر التحكم المجمع في نموذج مثل أي Windows غير ذلك نماذج عنصر التحكم.

تتضمن المهام الموضحة في هذه الإرشادات التفصيلية ما يلي:

  • إنشاء المشروع

  • إنشاء عنصر تحكم مكتبة المشروع

  • الرجوع إلى مشروع عنصر تحكم مخصص

  • تعريف عنصر تحكم مخصص و الخاص مصمم مخصص

  • قم بإنشاء مثيل لجهاز عنصر تحكم مخصص

  • إعداد المشروع لتصحيح وقت التصميم .

  • تطبيق عنصر تحكم مخصص الخاص بك

  • قم بإنشاء عنصر تحكم فرع لجهاز عنصر تحكم مخصص

  • إنشاء الفرعة MarqueeBorder عنصر تحكم

  • إنشاء Cusإلىm مصمم إلى الظل وخصائص عامل تصفية

  • معالجة التغييرات في المكونات

  • إضافة أفعال مصمم إلى مصمم Cusإلىm الخاص بك

  • إنشاء UITypeEditor مخصص

  • اختبار جهاز عنصر تحكم مخصص في "مصمم"

عند الانتهاء، الخاص بك عنصر تحكم مخصص تبدو شيء كما يلي:

اتفاقية MarqueeControl ممكنة

لقائمة كاملة من تعليمات برمجية، راجع كيفية: إنشاء عنصر تحكم نماذج Windows التي يأخذ ميزة ميزات وقت التصميم.

ملاحظة

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

المتطلبات الأساسية

لإكمال هذه المعاينة ، سوف تحتاج إلى :

  • permهوsions كافية لكي تكون قادراً تشغيل إنشاء وتشغيل مشاريع تطبيق Windows Forms تشغيل الكمبيوتر الموقع Studio Vهوual هو مثبتة.

إنشاء المشروع

الخطوة الأولى هو لإنشاء مشروع تطبيق. سيتم استخدام هذا مشروع لإنشاء تطبيق الذي يستضيف المخصصة عنصر تحكم.

لإنشاء المشروع

إنشاء عنصر تحكم مكتبة المشروع

وتتمثل الخطوة التالية لإنشاء عنصر تحكم مشروع المكتبة. يتم إنشاء عنصر تحكم مخصص جديد و به مصمم المخصص المطابق.

لإنشاء عنصر تحكم مكتبة المشروع

  1. إضافة مشروع مكتبة التحكم النماذج Windows إلى الحل. لمزيد من المعلومات، راجع Add New Project Dialog Box. اسم مشروع "MarqueeControlLibrary".

  2. استخدام مستكشف الحلول، بيحذف عنصر التحكم الافتراضي للمشروع بواسطة يحذف المصدر ملف المسمى "UserControl1.cs" أو "UserControl1.vb"، وفقا للغة الخاصة بك من الاختيارك. لمزيد من المعلومات، راجع كيفية القيام بما يلي: إزالة ,حذف و استبعاد عناصر.

  3. إضافة جديد UserControlالعنصر إلى MarqueeControlLibraryمشروع. قم بإعطاء مصدر جديد ملف اسم أساسي من "MarqueeControl".

  4. مستكشف الحل، استخدام إنشاء مجلد جديد في MarqueeControlLibraryمشروع. لمزيد من المعلومات، راجع كيفية القيام بما يلي: عناصر المشروع إضافة جديد. الاسم الجديد مجلد "تصميم".

  5. انقر نقراً مزدوجاً فوق المجلد تصميم و إضافة فئة جديدة. قم بإعطاء المصدر ملف اسم أساسي من "MarqueeControlRootDesigner".

  6. ستحتاج إلى استخدام أنواع من تجميع النظام.تصميم، أضف هذا مرجع إلى MarqueeControlLibraryمشروع. لمزيد من المعلومات، راجع How to: Add and Remove References in Visual Studio (C#).

الرجوع إلى مشروع عنصر تحكم مخصص

يمكنك استخدام MarqueeControlTestمشروع لاختبار المخصصة عنصر تحكم. تصبح على علم المخصصة المشروع اختبار التحكم متى قمت إضافة مرجع مشروع إلى MarqueeControlLibraryتجميع.

إلى مرجع مشروع عنصر تحكم cusإلىm

  • في MarqueeControlTestللمشروع، قم بإضافة مرجع مشروع إلى MarqueeControlLibraryتجميع. تأكد من استخدام علامة تبويب مشاريع في صندوق الحوار إضافة المرجع بدلاً من الرجوع إلى MarqueeControlLibraryتجميع مباشرة.

تعريف عنصر تحكم مخصص و الخاص مصمم مخصص

الخاص بك عنصر تحكم مخصص سوف ينحدر من UserControlفئة. يسمح هذا عنصر تحكم لاحتواء s عنصر تحكم الأخرى، ويعطي الخاص بك عنصر تحكم قدر كبير من الوظائف بشكل افتراضي.

الخاص بك عنصر تحكم مخصص سيكون مصمم مخصصة مقترنة. وهذا يسمح لك بإنشاء عمل تصميم فريد مفصلة خصيصا للمخصص الخاص بك عنصر تحكم.

يجب إقران عنصر تحكم مع المصمم الخاصة به باستخدام DesignerAttributeفئة. حيث أنك تقوم بتطوير كامل لوقت التصميم سلوك الخاص بك مخصص عنصر التحكم، مخصص سيتم تطبيق مصمم IRootDesignerالواجهة.

إلى تعريف عنصر تحكم cusإلىm ومصمم cusإلىm الخاص به

  1. بفتح MarqueeControlمصدر ملف في محرر تعليمات برمجية. في الأعلى من الملف، قم باستيراد مساحات الاسم التالية:

    Imports System
    Imports System.Collections
    Imports System.ComponentModel
    Imports System.ComponentModel.Design
    Imports System.Drawing
    Imports System.Windows.Forms
    Imports System.Windows.Forms.Design
    
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;
    
  2. إضافة DesignerAttributeإلى MarqueeControlإعلان الفئة. هذا يقوم بربط عنصر تحكم مخصص مع به مصمم.

    <Designer(GetType(MarqueeControlLibrary.Design.MarqueeControlRootDesigner), _
     GetType(IRootDesigner))> _
    Public Class MarqueeControl
        Inherits UserControl
    
        [Designer( typeof( MarqueeControlLibrary.Design.MarqueeControlRootDesigner ), typeof( IRootDesigner ) )]
        public class MarqueeControl : UserControl
        {
    
  3. بفتح MarqueeControlRootDesignerمصدر ملف في محرر تعليمات برمجية. في الأعلى من الملف، قم باستيراد مساحات الاسم التالية:

    Imports System
    Imports System.Collections
    Imports System.ComponentModel
    Imports System.ComponentModel.Design
    Imports System.Diagnostics
    Imports System.Drawing.Design
    Imports System.Windows.Forms
    Imports System.Windows.Forms.Design
    
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Drawing.Design;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;
    
  4. قم بتغيير التصريح MarqueeControlRootDesignerإلى يورث DocumentDesignerفئة. يطبق ToolboxItemFilterAttributeلتحديد المصمم تفاعل مع من مربع الأدوات.

    ملاحظةالتعريف ل MarqueeControlRootDesignerفئة له تم تضمينه في مساحة الاسم ما يسمى "MarqueeControlLibrary.تصميم". يضع هذا التعريف مصمم في مساحة الاسم خاص بحجز للأنواع ذات الصلة بالتصميم.

    Namespace MarqueeControlLibrary.Design
    
        <ToolboxItemFilter("MarqueeControlLibrary.MarqueeBorder", _
        ToolboxItemFilterType.Require), _
        ToolboxItemFilter("MarqueeControlLibrary.MarqueeText", _
        ToolboxItemFilterType.Require)> _
        <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
        Public Class MarqueeControlRootDesigner
            Inherits DocumentDesigner
    
    namespace MarqueeControlLibrary.Design
    {
        [ToolboxItemFilter("MarqueeControlLibrary.MarqueeBorder", ToolboxItemFilterType.Require)]
        [ToolboxItemFilter("MarqueeControlLibrary.MarqueeText", ToolboxItemFilterType.Require)]
        [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
        public class MarqueeControlRootDesigner : DocumentDesigner
        {
    
  5. تعرف الدالة الإنشائية ل MarqueeControlRootDesignerفئة. إدراج WriteLineكشف في نص المنشئ. سوف يكون هذا مفيداً ل تصحيح الأخطاء الأغراض.

    Public Sub New()
        Trace.WriteLine("MarqueeControlRootDesigner ctor")
    End Sub
    
    public MarqueeControlRootDesigner()
    {
        Trace.WriteLine("MarqueeControlRootDesigner ctor");
    }
    

قم بإنشاء مثيل لجهاز عنصر تحكم مخصص

لمراقبة سلوك وقت التصميم المخصص لجهاز عنصر تحكم، سيتم وضع نسخة عن الخاص بك عنصر تحكم تشغيل النموذج في MarqueeControlTestمشروع.

لإنشاء مثيل المخصص الخاص بك عنصر تحكم

  1. إضافة جديد UserControlالعنصر إلى MarqueeControlTestمشروع. قم بإعطاء مصدر جديد ملف اسم أساسي من "DemoMarqueeControl".

  2. بفتح DemoMarqueeControlملف في محرر تعليمات برمجية. في الأعلى ملف، قم باستيراد MarqueeControlLibraryمساحة الاسم:

Imports MarqueeControlLibrary
using MarqueeControlLibrary;
  1. قم بتغيير التصريح DemoMarqueeControlإلى يورث MarqueeControlفئة.

  2. إنشاء المشروع.

  3. افتح Form1 في مصمم Windows Forms .

  4. ابحث عن علامة تبويب MarqueeControlTest مكونات في من مربع الأدوات و فتح عليه. بسحب DemoMarqueeControlمن مربع أدوات التحكم على النموذج الخاص بك.

  5. إنشاء المشروع.

إعداد المشروع لتصحيح وقت التصميم .

عندما تقوم بتطوير عمل مخصصة لوقت التصميم، يكون ضروريا التصحيح الخاص بك عناصر التحكم والمكونات. هناك هو طريقة بسيطة لإعداد المشروع الخاص بك للسماح بتصحيح الأخطاء في وقت التصميم. لمزيد من المعلومات، راجع الإرشادات التفصيلية: تصحيح أخطاء عناصر تحكم Windows Forms المخصصة في وقت التصميم.

لإعداد مشروع لتصحيح الأخطاء في وقت التصميم

  1. يمين-انقر فوق MarqueeControlLibraryمشروع وحدد خصائص.

  2. في صندوق الحوار "الصفحات الخاصية MarqueeControlLibrary"، تحديد الصفحة يصحح.

  3. في مقطع بدء إجراء ، تحديد بدء البرامج خارجي . سيكون بتصحيح نسخة منفصلة من ‏‫Visual Studio، لذا انقر فوق علامة القطع ( لقطة شاشة لـ VisualStudioEllipsesButton) زر للاستعراض بحثاً عن برنامج ‏‫Visual Studio IDE. اسم الملف التنفيذي ملف devenv.exe، وإذا قمت بتثبيت إلى الموقع الافتراضي، يكون مسار%programملفs%\Microsoft 9.0\Common7\IDE\devenv.exe ‏‫Visual Studio.

  4. انقر فوق موافق لإغلاق مربع الحوار.

  5. بزر الماوس الأيمن فوق MarqueeControlLibraryللمشروع وحدد "تعيين كبدء التشغيل مشروع" إلى تمكين هذا تكوين تصحيح.

Checkpoint (نقطة التحقق)

أنت الآن جاهز لتصحيح سلوك وقت التصميم الخاص بك مخصص عنصر تحكم. بمجرد تحديد التي بيئة التصحيح هو إعداد بشكل صحيح، سيتم اختبار الاقتران بين عنصر التحكم المخصص والمصمم المخصصة.

إلى اختبار بيئة التصحيح والمصمم الاقتران

  1. بفتح MarqueeControlRootDesignerمصدر ملف في محرر تعليمات برمجية ومكان نقطة توقف تشغيل WriteLineالعبارة.

  2. اضغط F5 لتشغيل جلسة التصحيح . لاحظ أن نسخة جديدة من ‏‫Visual Studio يتم إنشاؤه.

  3. في مثيل جديد من برنامج ‏‫Visual Studio، قم بفتح الحل "MarqueeControlTest". يمكنك بسهولة بحث الحل بتحديد مشاريع الأخيرة من قائمة ملف. سيتم سرد الملف الحل "MarqueeControlTest.sln" كالملفات المستخدمة مؤخرا.

  4. بفتح DemoMarqueeControlفي مصمم. لاحظ أن تصحيح الأخطاء مثيل ل ‏‫Visual Studio تكتسب تركيز ويتوقف التنفيذ عند نقطة إيقاف الخاص بك. اضغط على F5 إلى متابعة جلسة عمل التصحيح.

في ترتيب هو الإشارة، كل شيء هو في مكان لتطوير وتصحيح الأخطاء عنصر التحكم المخصص والمصمم المخصصة المقترن به. يقوم الجزء المتبقي من هذه معاينة بالتركيز تشغيل التفاصيل الخاصة بتطبيق ميزات عنصر تحكم والمصمم.

تطبيق عنصر تحكم مخصص الخاص بك

MarqueeControlهو UserControlبقليل قليل من التخصيص. الكشف عن اثنين وظائف: Start، الذي يبدأ حركة الشاشة الاسمية، وStop، الذي توقف عن رسم متحرك. لأن MarqueeControlيتضمن التابعة عنصر تحكم s تطبيق IMarqueeWidgetالواجهة، Startو Stopتعداد كل طفل عنصر تحكم واستدعاء StartMarqueeو StopMarqueeوظائف، تشغيل التوالي، في كل طفل عنصر تحكم الذي يقوم بتنفيذ IMarqueeWidget.

شكل MarqueeBorderو MarqueeTextعناصر تحكم هو تعتمد تشغيل التخطيط، حتى MarqueeControlيتجاوز OnLayoutمكالمات وأسلوب PerformLayoutتشغيل عناصر التحكم التابعة لترتيب هو النوع.

هذا هو المدى MarqueeControlالتخصيصات. يتم تطبيق ميزات وقت التشغيل بواسطة MarqueeBorderو MarqueeTextتطبيق عناصر التحكم والميزات لوقت التصميم بواسطة MarqueeBorderDesignerو MarqueeControlRootDesignerفئات.

لتطبيق المخصص الخاص بك عنصر تحكم

  1. بفتح MarqueeControlمصدر ملف في محرر تعليمات برمجية. تطبيق Startو Stopوظائف.

    Public Sub Start()
        ' The MarqueeControl may contain any number of 
        ' controls that implement IMarqueeWidget, so 
        ' find each IMarqueeWidget child and call its
        ' StartMarquee method.
        Dim cntrl As Control
        For Each cntrl In Me.Controls
            If TypeOf cntrl Is IMarqueeWidget Then
                Dim widget As IMarqueeWidget = CType(cntrl, IMarqueeWidget)
    
                widget.StartMarquee()
            End If
        Next cntrl
    End Sub
    
    
    Public Sub [Stop]()
        ' The MarqueeControl may contain any number of 
        ' controls that implement IMarqueeWidget, so find
        ' each IMarqueeWidget child and call its StopMarquee
        ' method.
        Dim cntrl As Control
        For Each cntrl In Me.Controls
            If TypeOf cntrl Is IMarqueeWidget Then
                Dim widget As IMarqueeWidget = CType(cntrl, IMarqueeWidget)
    
                widget.StopMarquee()
            End If
        Next cntrl
    End Sub
    
    public void Start()
    {
        // The MarqueeControl may contain any number of 
        // controls that implement IMarqueeWidget, so 
        // find each IMarqueeWidget child and call its
        // StartMarquee method.
        foreach( Control cntrl in this.Controls )
        {
            if( cntrl is IMarqueeWidget )
            {
                IMarqueeWidget widget = cntrl as IMarqueeWidget;
                widget.StartMarquee();
            }
        }
    }
    
    public void Stop()
    {
        // The MarqueeControl may contain any number of 
        // controls that implement IMarqueeWidget, so find
        // each IMarqueeWidget child and call its StopMarquee
        // method.
        foreach( Control cntrl in this.Controls )
        {
            if( cntrl is IMarqueeWidget )
            {
                IMarqueeWidget widget = cntrl as IMarqueeWidget;
                widget.StopMarquee();
            }
        }
    }
    
  2. تجاوز الأسلوب OnLayout.

    Protected Overrides Sub OnLayout(ByVal levent As LayoutEventArgs)
        MyBase.OnLayout(levent)
    
        ' Repaint all IMarqueeWidget children if the layout 
        ' has changed.
        Dim cntrl As Control
        For Each cntrl In Me.Controls
            If TypeOf cntrl Is IMarqueeWidget Then
                Dim widget As IMarqueeWidget = CType(cntrl, IMarqueeWidget)
    
                cntrl.PerformLayout()
            End If
        Next cntrl
    End Sub
    
    protected override void OnLayout(LayoutEventArgs levent)
    {
        base.OnLayout (levent);
    
        // Repaint all IMarqueeWidget children if the layout 
        // has changed.
        foreach( Control cntrl in this.Controls )
        {
            if( cntrl is IMarqueeWidget )
            {
                Control control = cntrl as Control; 
    
                control.PerformLayout();
            }
        }
    }
    

قم بإنشاء عنصر تحكم فرع لجهاز عنصر تحكم مخصص

MarqueeControlسيستضيف نوعين من تابع عنصر تحكم: theMarqueeBorderعنصر تحكم and theMarqueeTextعنصر تحكم.

  • MarqueeBorder: هذا عنصر تحكم رسم حدود "اضواء" حول حواف به. وميض الأضواء في تسلسل، حيث تظهر إلى أن التنقل إلى الحد. سرعة وميض الأضواء هو التحكم بواسطة خاصية تسمى UpdatePeriod. تحدد العديد من الخصائص الأخرى المخصصة الأوجه الأخرى الخاصة بشكل عنصر تحكم's. طريقتين تسمى StartMarqueeو StopMarquee، عنصر تحكم عند بدء تشغيل رسم متحرك وعلامات.

  • MarqueeText: هذا عنصر تحكم رسم سلسلة امض. مثل MarqueeBorderعنصر تحكم، تكون سرعة وميض نص عنصر تحكم الافتتاح UpdatePeriodخاصية. MarqueeTextعلى عنصر التحكم أيضا StartMarqueeو StopMarqueeوظائف من الميزات المشتركة مع MarqueeBorderعنصر التحكم.

وقت التصميم، MarqueeControlRootDesignerتسمح هذه اثنين عنصر تحكم أنواع المراد إضافتها إلى MarqueeControlفي أي تركيبة.

ميزات عام الثاني هي factored عناصر التحكم في واجهة استدعاء IMarqueeWidget. وهذا ما يسمح MarqueeControlلاكتشاف أي نص متحرك-المتعلقة بعناصر التحكم التابعة وإعطائها المعاملة الخاصة.

إلى تطبيق الميزة رسم متحرك الدورية، يمكنك استخدام BackgroundWorkerالكائنات من System.ComponentModelمساحة الاسم. يمكنك استخدام Timerالكائنات، ولكن عند العديد من IMarqueeWidgetكائنات موجودة، قد لا يتمكن مؤشر ترابط مفرد لواجهة المستخدم إلى مجاراة الحركة.

إلى إنشاء عنصر تحكم تابعا لعنصر التحكم المخصص الخاص بك

  1. إضافة فئة جديدة العنصر إلى MarqueeControlLibraryمشروع. قم بإعطاء مصدر جديد ملف اسم أساسي من "IMarqueeWidget".

  2. بفتح IMarqueeWidgetمصدر ملف في محرر تعليمات برمجية وتغيير التعريف من classإلى interface:

    ' This interface defines the contract for any class that is to
    ' be used in constructing a MarqueeControl.
    Public Interface IMarqueeWidget
    
    // This interface defines the contract for any class that is to
    // be used in constructing a MarqueeControl.
    public interface IMarqueeWidget
    {
    
  3. قم بإضافة التعليمة البرمجية التالية إلى IMarqueeWidgetواجهة لعرض خاصية التعامل معها وأساليب الثاني نص متحرك الحركة:

    ' This interface defines the contract for any class that is to
    ' be used in constructing a MarqueeControl.
    Public Interface IMarqueeWidget
    
       ' This method starts the animation. If the control can 
       ' contain other classes that implement IMarqueeWidget as
       ' children, the control should call StartMarquee on all
       ' its IMarqueeWidget child controls.
       Sub StartMarquee()
    
       ' This method stops the animation. If the control can 
       ' contain other classes that implement IMarqueeWidget as
       ' children, the control should call StopMarquee on all
       ' its IMarqueeWidget child controls.
       Sub StopMarquee()
    
       ' This method specifies the refresh rate for the animation,
       ' in milliseconds.
       Property UpdatePeriod() As Integer
    
    End Interface
    
    // This interface defines the contract for any class that is to
    // be used in constructing a MarqueeControl.
    public interface IMarqueeWidget
    {
        // This method starts the animation. If the control can 
        // contain other classes that implement IMarqueeWidget as
        // children, the control should call StartMarquee on all
        // its IMarqueeWidget child controls.
        void StartMarquee();
    
        // This method stops the animation. If the control can 
        // contain other classes that implement IMarqueeWidget as
        // children, the control should call StopMarquee on all
        // its IMarqueeWidget child controls.
        void StopMarquee();
    
        // This method specifies the refresh rate for the animation,
        // in milliseconds.
        int UpdatePeriod
        {
            get;
            set;
        }
    }
    
  4. إضافة عنصر جديد عنصر تحكم مخصص إلى MarqueeControlLibraryمشروع. قم بإعطاء مصدر جديد ملف اسم أساسي من "MarqueeText".

  5. بسحب BackgroundWorkerمكوّن من مربع أدوات التحكم إلى الخاصة بك MarqueeTextعنصر تحكم. سيسمح هذا مكوّن MarqueeTextعنصر تحكم بتحديث نفسها بشكل غير متزامن.

  6. في خصائص النافذة، قم بتعيين و BackgroundWorkerمكوّنWorkerReportsProgess WorkerSupportsCancellationخصائص إلى true. يتيح هذان الإعدادان BackgroundWorkerمكوّن إلى رفع بشكل دوري ProgressChangedحدث و إلى إلغاء التحديثات غير متزامنة. لمزيد من المعلومات، راجع مكوّن BackgroundWorker.

  7. بفتح MarqueeTextمصدر ملف في محرر تعليمات برمجية. في الأعلى من الملف، قم باستيراد مساحات الاسم التالية:

    Imports System
    Imports System.ComponentModel
    Imports System.ComponentModel.Design
    Imports System.Diagnostics
    Imports System.Drawing
    Imports System.Threading
    Imports System.Windows.Forms
    Imports System.Windows.Forms.Design
    
    using System;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Drawing;
    using System.Threading;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;
    
  8. قم بتغيير التصريح MarqueeTextإلى يورث Labelو إلى تطبيق IMarqueeWidgetواجهة:

    <ToolboxItemFilter("MarqueeControlLibrary.MarqueeText", _
    ToolboxItemFilterType.Require)> _
    Partial Public Class MarqueeText
        Inherits Label
        Implements IMarqueeWidget
    
    [ToolboxItemFilter("MarqueeControlLibrary.MarqueeText", ToolboxItemFilterType.Require)]
    public partial class MarqueeText : Label, IMarqueeWidget
    {
    
  9. تعريف متغيرات المثيل التي تتوافق مع إلى الخصائص المكشوفة، ويهيّئ هذه في construcإلىr. isLitالحقل بتحديد ما إذا كان نص هو أن يتم تلوين باللون المعطى من قبل LightColorخاصية.

    ' When isLit is true, the text is painted in the light color;
    ' When isLit is false, the text is painted in the dark color.
    ' This value changes whenever the BackgroundWorker component
    ' raises the ProgressChanged event.
    Private isLit As Boolean = True
    
    ' These fields back the public properties.
    Private updatePeriodValue As Integer = 50
    Private lightColorValue As Color
    Private darkColorValue As Color
    
    ' These brushes are used to paint the light and dark
    ' colors of the text.
    Private lightBrush As Brush
    Private darkBrush As Brush
    
    ' This component updates the control asynchronously.
    Private WithEvents backgroundWorker1 As BackgroundWorker
    
    
    Public Sub New()
        ' This call is required by the Windows.Forms Form Designer.
        InitializeComponent()
    
        ' Initialize light and dark colors 
        ' to the control's default values.
        Me.lightColorValue = Me.ForeColor
        Me.darkColorValue = Me.BackColor
        Me.lightBrush = New SolidBrush(Me.lightColorValue)
        Me.darkBrush = New SolidBrush(Me.darkColorValue)
    End Sub 'New
    
    // When isLit is true, the text is painted in the light color;
    // When isLit is false, the text is painted in the dark color.
    // This value changes whenever the BackgroundWorker component
    // raises the ProgressChanged event.
    private bool isLit = true;
    
    // These fields back the public properties.
    private int updatePeriodValue = 50;
    private Color lightColorValue;
    private Color darkColorValue;
    
    // These brushes are used to paint the light and dark
    // colors of the text.
    private Brush lightBrush;
    private Brush darkBrush;
    
    // This component updates the control asynchronously.
    private BackgroundWorker backgroundWorker1;
    
    public MarqueeText()
    {
        // This call is required by the Windows.Forms Form Designer.
        InitializeComponent();
    
        // Initialize light and dark colors 
        // to the control's default values.
        this.lightColorValue = this.ForeColor;
        this.darkColorValue = this.BackColor;
        this.lightBrush = new SolidBrush(this.lightColorValue);
        this.darkBrush = new SolidBrush(this.darkColorValue);
    }
    
  10. تطبيق واجهة IMarqueeWidget .

    StartMarqueeو StopMarqueeاستدعاء الوظائف و BackgroundWorkerمكوّنRunWorkerAsync CancelAsyncوظائف إلى البداية و sإلىp رسم متحرك.

    Categoryو Browsableيتم تطبيق السمات على UpdatePeriodخاصية حتى يظهر في مقطع مخصص من النافذة "خصائص" تسمى "نص متحرك."

    Public Overridable Sub StartMarquee() _
    Implements IMarqueeWidget.StartMarquee
        ' Start the updating thread and pass it the UpdatePeriod.
        Me.backgroundWorker1.RunWorkerAsync(Me.UpdatePeriod)
    End Sub
    
    Public Overridable Sub StopMarquee() _
    Implements IMarqueeWidget.StopMarquee
        ' Stop the updating thread.
        Me.backgroundWorker1.CancelAsync()
    End Sub
    
    
    <Category("Marquee"), Browsable(True)> _
    Public Property UpdatePeriod() As Integer _
    Implements IMarqueeWidget.UpdatePeriod
    
        Get
            Return Me.updatePeriodValue
        End Get
    
        Set(ByVal Value As Integer)
            If Value > 0 Then
                Me.updatePeriodValue = Value
            Else
                Throw New ArgumentOutOfRangeException("UpdatePeriod", "must be > 0")
            End If
        End Set
    
    End Property
    
    public virtual void StartMarquee()
    {
        // Start the updating thread and pass it the UpdatePeriod.
        this.backgroundWorker1.RunWorkerAsync(this.UpdatePeriod);
    }
    
    public virtual void StopMarquee()
    {
        // Stop the updating thread.
        this.backgroundWorker1.CancelAsync();
    }
    
    [Category("Marquee")]
    [Browsable(true)]
    public int UpdatePeriod
    {
        get
        {
            return this.updatePeriodValue;
        }
    
        set
        {
            if (value > 0)
            {
                this.updatePeriodValue = value;
            }
            else
            {
                throw new ArgumentOutOfRangeException("UpdatePeriod", "must be > 0");
            }
        }
    }
    
  11. تطبيق accessors خاصية. سوف تعرض خاصيتين إلى العملاء: LightColor وDarkColor Categoryو Browsableيتم تطبيق سمات إلى هذه الخصائص، حيث تظهر الخصائص في مقطع cusإلىm من النافذة "خصائص" تسمى "الشاشه الاسمية."

    <Category("Marquee"), Browsable(True)> _
    Public Property LightColor() As Color
    
        Get
            Return Me.lightColorValue
        End Get
    
        Set(ByVal Value As Color)
            ' The LightColor property is only changed if the 
            ' client provides a different value. Comparing values 
            ' from the ToArgb method is the recommended test for
            ' equality between Color structs.
            If Me.lightColorValue.ToArgb() <> Value.ToArgb() Then
                Me.lightColorValue = Value
                Me.lightBrush = New SolidBrush(Value)
            End If
        End Set
    
    End Property
    
    
    <Category("Marquee"), Browsable(True)> _
    Public Property DarkColor() As Color
    
        Get
            Return Me.darkColorValue
        End Get
    
        Set(ByVal Value As Color)
            ' The DarkColor property is only changed if the 
            ' client provides a different value. Comparing values 
            ' from the ToArgb method is the recommended test for
            ' equality between Color structs.
            If Me.darkColorValue.ToArgb() <> Value.ToArgb() Then
                Me.darkColorValue = Value
                Me.darkBrush = New SolidBrush(Value)
            End If
        End Set
    
    End Property
    
    [Category("Marquee")]
    [Browsable(true)]
    public Color LightColor
    {
        get
        {
            return this.lightColorValue;
        }
        set
        {
            // The LightColor property is only changed if the 
            // client provides a different value. Comparing values 
            // from the ToArgb method is the recommended test for
            // equality between Color structs.
            if (this.lightColorValue.ToArgb() != value.ToArgb())
            {
                this.lightColorValue = value;
                this.lightBrush = new SolidBrush(value);
            }
        }
    }
    
    [Category("Marquee")]
    [Browsable(true)]
    public Color DarkColor
    {
        get
        {
            return this.darkColorValue;
        }
        set
        {
            // The DarkColor property is only changed if the 
            // client provides a different value. Comparing values 
            // from the ToArgb method is the recommended test for
            // equality between Color structs.
            if (this.darkColorValue.ToArgb() != value.ToArgb())
            {
                this.darkColorValue = value;
                this.darkBrush = new SolidBrush(value);
            }
        }
    }
    
  12. قم بتطبيق معالجات و BackgroundWorkerمكوّنDoWork ProgressChangedأحداث.

    DoWorkسكون معالج الأحداث لعدد المللي ثانية المعين بواسطة UpdatePeriodثم يرفع ProgressChangedحدث، حتى يتوقف تعليمات برمجية للحركة بواسطة استدعاء CancelAsync.

    ProgressChangedمعالج الأحداث إلى ggles نص بين حالته الضوء والمعتمة إلى إعطاء المظهر وامض.

    ' This method is called in the worker thread's context, 
    ' so it must not make any calls into the MarqueeText control.
    ' Instead, it communicates to the control using the 
    ' ProgressChanged event.
    '
    ' The only work done in this event handler is
    ' to sleep for the number of milliseconds specified 
    ' by UpdatePeriod, then raise the ProgressChanged event.
    Private Sub backgroundWorker1_DoWork( _
    ByVal sender As Object, _
    ByVal e As System.ComponentModel.DoWorkEventArgs) _
    Handles backgroundWorker1.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
    
        ' This event handler will run until the client cancels
        ' the background task by calling CancelAsync.
        While Not worker.CancellationPending
            ' The Argument property of the DoWorkEventArgs
            ' object holds the value of UpdatePeriod, which 
            ' was passed as the argument to the RunWorkerAsync
            ' method. 
            Thread.Sleep(Fix(e.Argument))
    
            ' The DoWork eventhandler does not actually report
            ' progress; the ReportProgress event is used to 
            ' periodically alert the control to update its state.
            worker.ReportProgress(0)
        End While
    End Sub
    
    
    ' The ProgressChanged event is raised by the DoWork method.
    ' This event handler does work that is internal to the
    ' control. In this case, the text is toggled between its
    ' light and dark state, and the control is told to 
    ' repaint itself.
    Private Sub backgroundWorker1_ProgressChanged( _
    ByVal sender As Object, _
    ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
    Handles backgroundWorker1.ProgressChanged
        Me.isLit = Not Me.isLit
        Me.Refresh()
    End Sub
    
            // This method is called in the worker thread's context, 
            // so it must not make any calls into the MarqueeText control.
            // Instead, it communicates to the control using the 
            // ProgressChanged event.
            //
            // The only work done in this event handler is
            // to sleep for the number of milliseconds specified 
            // by UpdatePeriod, then raise the ProgressChanged event.
            private void backgroundWorker1_DoWork(
                object sender,
                System.ComponentModel.DoWorkEventArgs e)
            {
                BackgroundWorker worker = sender as BackgroundWorker;
    
                // This event handler will run until the client cancels
                // the background task by calling CancelAsync.
                while (!worker.CancellationPending)
                {
                    // The Argument property of the DoWorkEventArgs
                    // object holds the value of UpdatePeriod, which 
                    // was passed as the argument to the RunWorkerAsync
                    // method. 
                    Thread.Sleep((int)e.Argument);
    
                    // The DoWork eventhandler does not actually report
                    // progress; the ReportProgress event is used to 
                    // periodically alert the control to update its state.
                    worker.ReportProgress(0);
                }
            }
    
            // The ProgressChanged event is raised by the DoWork method.
            // This event handler does work that is internal to the
            // control. In this case, the text is toggled between its
            // light and dark state, and the control is told to 
            // repaint itself.
            private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
            {
                this.isLit = !this.isLit;
                this.Refresh();
            }
    
    
  13. يمنع OnPaintأسلوب إلى تمكين رسم متحرك.

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        ' The text is painted in the light or dark color,
        ' depending on the current value of isLit.
        Me.ForeColor = IIf(Me.isLit, Me.lightColorValue, Me.darkColorValue)
    
        MyBase.OnPaint(e)
    End Sub
    
    protected override void OnPaint(PaintEventArgs e)
    {
        // The text is painted in the light or dark color,
        // depending on the current value of isLit.
        this.ForeColor =
            this.isLit ? this.lightColorValue : this.darkColorValue;
    
        base.OnPaint(e);
    }
    
  14. اضغط F6 لبناء الحل.

إنشاء الفرعة MarqueeBorder عنصر تحكم

MarqueeBorderعنصر تحكم هو قليلاً أكثر تعقيداً من MarqueeTextعنصر تحكم. له المزيد من خصائص ورسم متحرك في OnPaintأسلوب هو أكثر معنية. في المبدأ، فإنه يشبه تماما MarqueeTextعنصر تحكم.

لأن MarqueeBorderعنصر تحكم يمكن أن عنصر تحكم s التابعة، فإنه يجب أن يكون على علم Layoutالأحداث.

إلى بإنشاء عنصر تحكم MarqueeBorder

  1. إضافة عنصر جديد عنصر تحكم مخصص إلى MarqueeControlLibraryمشروع. تسمية الملف المصدر الجديد أساسية من "MarqueeBorder".

  2. بسحب BackgroundWorkerمكوّن من مربع أدوات التحكم إلى الخاصة بك MarqueeBorderعنصر تحكم. سيسمح هذا مكوّن MarqueeBorderعنصر تحكم بتحديث نفسها بشكل غير متزامن.

  3. في خصائص النافذة، قم بتعيين و BackgroundWorkerمكوّنWorkerReportsProgess WorkerSupportsCancellationخصائص إلى true. يتيح هذان الإعدادان BackgroundWorkerمكوّن إلى رفع بشكل دوري ProgressChangedحدث و إلى إلغاء التحديثات غير متزامنة. لمزيد من المعلومات، راجع مكوّن BackgroundWorker.

  4. في الإطار "خصائص"، انقر فوق أحداث زر. قم بإرفاق معالجات ل DoWorkو ProgressChangedالأحداث.

  5. بفتح MarqueeBorderمصدر ملف في محرر تعليمات برمجية. في الأعلى من الملف، قم باستيراد مساحات الاسم التالية:

    Imports System
    Imports System.ComponentModel
    Imports System.ComponentModel.Design
    Imports System.Diagnostics
    Imports System.Drawing
    Imports System.Drawing.Design
    Imports System.Threading
    Imports System.Windows.Forms
    Imports System.Windows.Forms.Design
    
    using System;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Drawing;
    using System.Drawing.Design;
    using System.Threading;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;
    
  6. قم بتغيير التصريح MarqueeBorderأن يورث من Panelو لتطبيق IMarqueeWidgetالواجهة.

    <Designer(GetType(MarqueeControlLibrary.Design.MarqueeBorderDesigner)), _
    ToolboxItemFilter("MarqueeControlLibrary.MarqueeBorder", _
    ToolboxItemFilterType.Require)> _
    Partial Public Class MarqueeBorder
        Inherits Panel
        Implements IMarqueeWidget
    
    [Designer(typeof(MarqueeControlLibrary.Design.MarqueeBorderDesigner ))]
    [ToolboxItemFilter("MarqueeControlLibrary.MarqueeBorder", ToolboxItemFilterType.Require)]
    public partial class MarqueeBorder : Panel, IMarqueeWidget
    {
    
  7. قم بتعريف التعدادات الثاني لإدارة MarqueeBorderعنصر تحكم للالولاية: MarqueeSpinDirection، الذي يحدد الاتجاه الذي الأضواء "التدوير" حول الحدود، وMarqueeLightShape، الذي يحدد شكل الأضواء (مربعة أو دائرية). قم بوضع هذه تصريحات قبل MarqueeBorderإعلان الفئة.

    ' This defines the possible values for the MarqueeBorder
    ' control's SpinDirection property.
    Public Enum MarqueeSpinDirection
       CW
       CCW
    End Enum
    
    ' This defines the possible values for the MarqueeBorder
    ' control's LightShape property.
    Public Enum MarqueeLightShape
        Square
        Circle
    End Enum
    
    // This defines the possible values for the MarqueeBorder
    // control's SpinDirection property.
    public enum MarqueeSpinDirection
    {
        CW,
        CCW
    }
    
    // This defines the possible values for the MarqueeBorder
    // control's LightShape property.
    public enum MarqueeLightShape
    {
        Square,
        Circle
    }
    
  8. تعريف متغيرات المثيل التي تتوافق مع إلى الخصائص المكشوفة، ويهيّئ هذه في construcإلىr.

    Public Shared MaxLightSize As Integer = 10
    
    ' These fields back the public properties.
    Private updatePeriodValue As Integer = 50
    Private lightSizeValue As Integer = 5
    Private lightPeriodValue As Integer = 3
    Private lightSpacingValue As Integer = 1
    Private lightColorValue As Color
    Private darkColorValue As Color
    Private spinDirectionValue As MarqueeSpinDirection = MarqueeSpinDirection.CW
    Private lightShapeValue As MarqueeLightShape = MarqueeLightShape.Square
    
    ' These brushes are used to paint the light and dark
    ' colors of the marquee lights.
    Private lightBrush As Brush
    Private darkBrush As Brush
    
    ' This field tracks the progress of the "first" light as it
    ' "travels" around the marquee border.
    Private currentOffset As Integer = 0
    
    ' This component updates the control asynchronously.
    Private WithEvents backgroundWorker1 As System.ComponentModel.BackgroundWorker
    
    
    Public Sub New()
        ' This call is required by the Windows.Forms Form Designer.
        InitializeComponent()
    
        ' Initialize light and dark colors 
        ' to the control's default values.
        Me.lightColorValue = Me.ForeColor
        Me.darkColorValue = Me.BackColor
        Me.lightBrush = New SolidBrush(Me.lightColorValue)
        Me.darkBrush = New SolidBrush(Me.darkColorValue)
    
        ' The MarqueeBorder control manages its own padding,
        ' because it requires that any contained controls do
        ' not overlap any of the marquee lights.
        Dim pad As Integer = 2 * (Me.lightSizeValue + Me.lightSpacingValue)
        Me.Padding = New Padding(pad, pad, pad, pad)
    
        SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
    End Sub
    
    public static int MaxLightSize = 10;
    
    // These fields back the public properties.
    private int updatePeriodValue = 50;
    private int lightSizeValue = 5;
    private int lightPeriodValue = 3;
    private int lightSpacingValue = 1;
    private Color lightColorValue;
    private Color darkColorValue;
    private MarqueeSpinDirection spinDirectionValue = MarqueeSpinDirection.CW;
    private MarqueeLightShape lightShapeValue = MarqueeLightShape.Square;
    
    // These brushes are used to paint the light and dark
    // colors of the marquee lights.
    private Brush lightBrush;
    private Brush darkBrush;
    
    // This field tracks the progress of the "first" light as it
    // "travels" around the marquee border.
    private int currentOffset = 0;
    
    // This component updates the control asynchronously.
    private System.ComponentModel.BackgroundWorker backgroundWorker1;
    
    public MarqueeBorder()
    {
        // This call is required by the Windows.Forms Form Designer.
        InitializeComponent();
    
        // Initialize light and dark colors 
        // to the control's default values.
        this.lightColorValue = this.ForeColor;
        this.darkColorValue = this.BackColor;
        this.lightBrush = new SolidBrush(this.lightColorValue);
        this.darkBrush = new SolidBrush(this.darkColorValue);
    
        // The MarqueeBorder control manages its own padding,
        // because it requires that any contained controls do
        // not overlap any of the marquee lights.
        int pad = 2 * (this.lightSizeValue + this.lightSpacingValue);
        this.Padding = new Padding(pad, pad, pad, pad);
    
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    }
    
  9. تطبيق واجهة IMarqueeWidget .

    StartMarqueeو StopMarqueeاستدعاء الوظائف و BackgroundWorkerمكوّنRunWorkerAsync CancelAsyncوظائف إلى البداية و sإلىp رسم متحرك.

    لأن MarqueeBorderعنصر تحكم يمكن أن تحتوي تشغيل عنصر تحكم s التابع StartMarqueeالطريقة تعداد الجميع مكالمات والتابعة عنصر تحكم s StartMarqueeتشغيل تلك التي تطبق IMarqueeWidget. StopMarqueeالأسلوب على تنفيذ مشابهة.

    Public Overridable Sub StartMarquee() _
    Implements IMarqueeWidget.StartMarquee
        ' The MarqueeBorder control may contain any number of 
        ' controls that implement IMarqueeWidget, so find
        ' each IMarqueeWidget child and call its StartMarquee
        ' method.
        Dim cntrl As Control
        For Each cntrl In Me.Controls
            If TypeOf cntrl Is IMarqueeWidget Then
                Dim widget As IMarqueeWidget = CType(cntrl, IMarqueeWidget)
    
                widget.StartMarquee()
            End If
        Next cntrl
    
        ' Start the updating thread and pass it the UpdatePeriod.
        Me.backgroundWorker1.RunWorkerAsync(Me.UpdatePeriod)
    End Sub
    
    
    Public Overridable Sub StopMarquee() _
    Implements IMarqueeWidget.StopMarquee
        ' The MarqueeBorder control may contain any number of 
        ' controls that implement IMarqueeWidget, so find
        ' each IMarqueeWidget child and call its StopMarquee
        ' method.
        Dim cntrl As Control
        For Each cntrl In Me.Controls
            If TypeOf cntrl Is IMarqueeWidget Then
                Dim widget As IMarqueeWidget = CType(cntrl, IMarqueeWidget)
    
                widget.StopMarquee()
            End If
        Next cntrl
    
        ' Stop the updating thread.
        Me.backgroundWorker1.CancelAsync()
    End Sub
    
    
    <Category("Marquee"), Browsable(True)> _
    Public Overridable Property UpdatePeriod() As Integer _
    Implements IMarqueeWidget.UpdatePeriod
    
        Get
            Return Me.updatePeriodValue
        End Get
    
        Set(ByVal Value As Integer)
            If Value > 0 Then
                Me.updatePeriodValue = Value
            Else
                Throw New ArgumentOutOfRangeException("UpdatePeriod", _
                "must be > 0")
            End If
        End Set
    
    End Property
    
            public virtual void StartMarquee()
            {
                // The MarqueeBorder control may contain any number of 
                // controls that implement IMarqueeWidget, so find
                // each IMarqueeWidget child and call its StartMarquee
                // method.
                foreach (Control cntrl in this.Controls)
                {
                    if (cntrl is IMarqueeWidget)
                    {
                        IMarqueeWidget widget = cntrl as IMarqueeWidget;
                        widget.StartMarquee();
                    }
                }
    
                // Start the updating thread and pass it the UpdatePeriod.
                this.backgroundWorker1.RunWorkerAsync(this.UpdatePeriod);
            }
    
            public virtual void StopMarquee()
            {
                // The MarqueeBorder control may contain any number of 
                // controls that implement IMarqueeWidget, so find
                // each IMarqueeWidget child and call its StopMarquee
                // method.
                foreach (Control cntrl in this.Controls)
                {
                    if (cntrl is IMarqueeWidget)
                    {
                        IMarqueeWidget widget = cntrl as IMarqueeWidget;
                        widget.StopMarquee();
                    }
                }
    
                // Stop the updating thread.
                this.backgroundWorker1.CancelAsync();
            }
    
            [Category("Marquee")]
            [Browsable(true)]
            public virtual int UpdatePeriod
            {
                get
                {
                    return this.updatePeriodValue;
                }
    
                set
                {
                    if (value > 0)
                    {
                        this.updatePeriodValue = value;
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException("UpdatePeriod", "must be > 0");
                    }
                }
            }
    
    
  10. تطبيق accessors خاصية. MarqueeBorderعنصر التحكم يحتوي على العديد من الخصائص للتحكم في المظهر الخاص به.

    <Category("Marquee"), Browsable(True)> _
    Public Property LightSize() As Integer
        Get
            Return Me.lightSizeValue
        End Get
    
        Set(ByVal Value As Integer)
            If Value > 0 AndAlso Value <= MaxLightSize Then
                Me.lightSizeValue = Value
                Me.DockPadding.All = 2 * Value
            Else
                Throw New ArgumentOutOfRangeException("LightSize", _
                "must be > 0 and < MaxLightSize")
            End If
        End Set
    End Property
    
    
    <Category("Marquee"), Browsable(True)> _
    Public Property LightPeriod() As Integer
        Get
            Return Me.lightPeriodValue
        End Get
    
        Set(ByVal Value As Integer)
            If Value > 0 Then
                Me.lightPeriodValue = Value
            Else
                Throw New ArgumentOutOfRangeException("LightPeriod", _
                "must be > 0 ")
            End If
        End Set
    End Property
    
    
    <Category("Marquee"), Browsable(True)> _
    Public Property LightColor() As Color
        Get
            Return Me.lightColorValue
        End Get
    
        Set(ByVal Value As Color)
            ' The LightColor property is only changed if the 
            ' client provides a different value. Comparing values 
            ' from the ToArgb method is the recommended test for
            ' equality between Color structs.
            If Me.lightColorValue.ToArgb() <> Value.ToArgb() Then
                Me.lightColorValue = Value
                Me.lightBrush = New SolidBrush(Value)
            End If
        End Set
    End Property
    
    
    <Category("Marquee"), Browsable(True)> _
    Public Property DarkColor() As Color
        Get
            Return Me.darkColorValue
        End Get
    
        Set(ByVal Value As Color)
            ' The DarkColor property is only changed if the 
            ' client provides a different value. Comparing values 
            ' from the ToArgb method is the recommended test for
            ' equality between Color structs.
            If Me.darkColorValue.ToArgb() <> Value.ToArgb() Then
                Me.darkColorValue = Value
                Me.darkBrush = New SolidBrush(Value)
            End If
        End Set
    End Property
    
    
    <Category("Marquee"), Browsable(True)> _
    Public Property LightSpacing() As Integer
        Get
            Return Me.lightSpacingValue
        End Get
    
        Set(ByVal Value As Integer)
            If Value >= 0 Then
                Me.lightSpacingValue = Value
            Else
                Throw New ArgumentOutOfRangeException("LightSpacing", _
                "must be >= 0")
            End If
        End Set
    End Property
    
    
    <Category("Marquee"), Browsable(True), _
    EditorAttribute(GetType(LightShapeEditor), _
    GetType(System.Drawing.Design.UITypeEditor))> _
    Public Property LightShape() As MarqueeLightShape
    
        Get
            Return Me.lightShapeValue
        End Get
    
        Set(ByVal Value As MarqueeLightShape)
            Me.lightShapeValue = Value
        End Set
    
    End Property
    
    
    <Category("Marquee"), Browsable(True)> _
    Public Property SpinDirection() As MarqueeSpinDirection
    
        Get
            Return Me.spinDirectionValue
        End Get
    
        Set(ByVal Value As MarqueeSpinDirection)
            Me.spinDirectionValue = Value
        End Set
    
    End Property
    
            [Category("Marquee")]
            [Browsable(true)]
            public int LightSize
            {
                get
                {
                    return this.lightSizeValue;
                }
    
                set
                {
                    if (value > 0 && value <= MaxLightSize)
                    {
                        this.lightSizeValue = value;
                        this.DockPadding.All = 2 * value;
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException("LightSize", "must be > 0 and < MaxLightSize");
                    }
                }
            }
    
            [Category("Marquee")]
            [Browsable(true)]
            public int LightPeriod
            {
                get
                {
                    return this.lightPeriodValue;
                }
    
                set
                {
                    if (value > 0)
                    {
                        this.lightPeriodValue = value;
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException("LightPeriod", "must be > 0 ");
                    }
                }
            }
    
            [Category("Marquee")]
            [Browsable(true)]
            public Color LightColor
            {
                get
                {
                    return this.lightColorValue;
                }
    
                set
                {
                    // The LightColor property is only changed if the 
                    // client provides a different value. Comparing values 
                    // from the ToArgb method is the recommended test for
                    // equality between Color structs.
                    if (this.lightColorValue.ToArgb() != value.ToArgb())
                    {
                        this.lightColorValue = value;
                        this.lightBrush = new SolidBrush(value);
                    }
                }
            }
    
            [Category("Marquee")]
            [Browsable(true)]
            public Color DarkColor
            {
                get
                {
                    return this.darkColorValue;
                }
    
                set
                {
                    // The DarkColor property is only changed if the 
                    // client provides a different value. Comparing values 
                    // from the ToArgb method is the recommended test for
                    // equality between Color structs.
                    if (this.darkColorValue.ToArgb() != value.ToArgb())
                    {
                        this.darkColorValue = value;
                        this.darkBrush = new SolidBrush(value);
                    }
                }
            }
    
            [Category("Marquee")]
            [Browsable(true)]
            public int LightSpacing
            {
                get
                {
                    return this.lightSpacingValue;
                }
    
                set
                {
                    if (value >= 0)
                    {
                        this.lightSpacingValue = value;
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException("LightSpacing", "must be >= 0");
                    }
                }
            }
    
            [Category("Marquee")]
            [Browsable(true)]
            [EditorAttribute(typeof(LightShapeEditor), 
                 typeof(System.Drawing.Design.UITypeEditor))]
            public MarqueeLightShape LightShape
            {
                get
                {
                    return this.lightShapeValue;
                }
    
                set
                {
                    this.lightShapeValue = value;
                }
            }
    
            [Category("Marquee")]
            [Browsable(true)]
            public MarqueeSpinDirection SpinDirection
            {
                get
                {
                    return this.spinDirectionValue;
                }
    
                set
                {
                    this.spinDirectionValue = value;
                }
            }
    
    
  11. قم بتطبيق معالجات و BackgroundWorkerمكوّنDoWork ProgressChangedأحداث.

    DoWorkسكون معالج الأحداث لعدد المللي ثانية المعين بواسطة UpdatePeriodثم يرفع ProgressChangedحدث، حتى يتوقف تعليمات برمجية للحركة بواسطة استدعاء CancelAsync.

    ProgressChangedمعالج الأحداث بزيادة موضع الضوء "الاساسي"، الذي الولاية الضوء/داكنه الأضواء الأخرى هو تحديد واستدعاء Refreshطريقة لجعل عنصر التحكم لإعادة رسم نفسه.

    ' This method is called in the worker thread's context, 
    ' so it must not make any calls into the MarqueeBorder
    ' control. Instead, it communicates to the control using 
    ' the ProgressChanged event.
    '
    ' The only work done in this event handler is
    ' to sleep for the number of milliseconds specified 
    ' by UpdatePeriod, then raise the ProgressChanged event.
    Private Sub backgroundWorker1_DoWork( _
    ByVal sender As Object, _
    ByVal e As System.ComponentModel.DoWorkEventArgs) _
    Handles backgroundWorker1.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
    
        ' This event handler will run until the client cancels
        ' the background task by calling CancelAsync.
        While Not worker.CancellationPending
            ' The Argument property of the DoWorkEventArgs
            ' object holds the value of UpdatePeriod, which 
            ' was passed as the argument to the RunWorkerAsync
            ' method. 
            Thread.Sleep(Fix(e.Argument))
    
            ' The DoWork eventhandler does not actually report
            ' progress; the ReportProgress event is used to 
            ' periodically alert the control to update its state.
            worker.ReportProgress(0)
        End While
    End Sub
    
    
    ' The ProgressChanged event is raised by the DoWork method.
    ' This event handler does work that is internal to the
    ' control. In this case, the currentOffset is incremented,
    ' and the control is told to repaint itself.
    Private Sub backgroundWorker1_ProgressChanged( _
    ByVal sender As Object, _
    ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
    Handles backgroundWorker1.ProgressChanged
        Me.currentOffset += 1
        Me.Refresh()
    End Sub
    
    // This method is called in the worker thread's context, 
    // so it must not make any calls into the MarqueeBorder
    // control. Instead, it communicates to the control using 
    // the ProgressChanged event.
    //
    // The only work done in this event handler is
    // to sleep for the number of milliseconds specified 
    // by UpdatePeriod, then raise the ProgressChanged event.
    private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
    
        // This event handler will run until the client cancels
        // the background task by calling CancelAsync.
        while (!worker.CancellationPending)
        {
            // The Argument property of the DoWorkEventArgs
            // object holds the value of UpdatePeriod, which 
            // was passed as the argument to the RunWorkerAsync
            // method. 
            Thread.Sleep((int)e.Argument);
    
            // The DoWork eventhandler does not actually report
            // progress; the ReportProgress event is used to 
            // periodically alert the control to update its state.
            worker.ReportProgress(0);
        }
    }
    
    // The ProgressChanged event is raised by the DoWork method.
    // This event handler does work that is internal to the
    // control. In this case, the currentOffset is incremented,
    // and the control is told to repaint itself.
    private void backgroundWorker1_ProgressChanged(
        object sender,
        System.ComponentModel.ProgressChangedEventArgs e)
    {
        this.currentOffset++;
        this.Refresh();
    }
    
  12. تنفيذ وظائف المساعد، IsLitو DrawLight.

    IsLitأسلوب تحديد اللون الضوء في موضع محدد. يتم رسم الأضواء هي "المشغله" باللون قدمها LightColorخاصية، و تلك الموجودة "الداكن" مأخوذة باللون المعطى من قبل DarkColorخاصية.

    DrawLightأسلوب يرسم ضوء باستخدام اللون المناسب، والشكل، و موضع.

    ' This method determines if the marquee light at lightIndex
    ' should be lit. The currentOffset field specifies where
    ' the "first" light is located, and the "position" of the
    ' light given by lightIndex is computed relative to this 
    ' offset. If this position modulo lightPeriodValue is zero,
    ' the light is considered to be on, and it will be painted
    ' with the control's lightBrush. 
    Protected Overridable Function IsLit(ByVal lightIndex As Integer) As Boolean
        Dim directionFactor As Integer = _
        IIf(Me.spinDirectionValue = MarqueeSpinDirection.CW, -1, 1)
    
        Return (lightIndex + directionFactor * Me.currentOffset) Mod Me.lightPeriodValue = 0
    End Function
    
    
    Protected Overridable Sub DrawLight( _
    ByVal g As Graphics, _
    ByVal brush As Brush, _
    ByVal xPos As Integer, _
    ByVal yPos As Integer)
    
        Select Case Me.lightShapeValue
            Case MarqueeLightShape.Square
                g.FillRectangle( _
                brush, _
                xPos, _
                yPos, _
                Me.lightSizeValue, _
                Me.lightSizeValue)
                Exit Select
            Case MarqueeLightShape.Circle
                g.FillEllipse( _
                brush, _
                xPos, _
                yPos, _
                Me.lightSizeValue, _
                Me.lightSizeValue)
                Exit Select
            Case Else
                Trace.Assert(False, "Unknown value for light shape.")
                Exit Select
        End Select
    
    End Sub
    
    // This method determines if the marquee light at lightIndex
    // should be lit. The currentOffset field specifies where
    // the "first" light is located, and the "position" of the
    // light given by lightIndex is computed relative to this 
    // offset. If this position modulo lightPeriodValue is zero,
    // the light is considered to be on, and it will be painted
    // with the control's lightBrush. 
    protected virtual bool IsLit(int lightIndex)
    {
        int directionFactor =
            (this.spinDirectionValue == MarqueeSpinDirection.CW ? -1 : 1);
    
        return (
            (lightIndex + directionFactor * this.currentOffset) % this.lightPeriodValue == 0
            );
    }
    
    protected virtual void DrawLight(
        Graphics g,
        Brush brush,
        int xPos,
        int yPos)
    {
        switch (this.lightShapeValue)
        {
            case MarqueeLightShape.Square:
                {
                    g.FillRectangle(brush, xPos, yPos, this.lightSizeValue, this.lightSizeValue);
                    break;
                }
            case MarqueeLightShape.Circle:
                {
                    g.FillEllipse(brush, xPos, yPos, this.lightSizeValue, this.lightSizeValue);
                    break;
                }
            default:
                {
                    Trace.Assert(false, "Unknown value for light shape.");
                    break;
                }
        }
    }
    
  13. يمنع OnLayoutو OnPaintوظائف.

    OnPaintأسلوب يرسم الأضواء بطول الحواف MarqueeBorderعنصر تحكم.

    لأن OnPaintتعتمد الطريقة تشغيل الأبعاد MarqueeBorderعنصر تحكم، تحتاج للاتصال به عند تغييرات تخطيط. إلى تحقيق ذلك، يمنع OnLayoutواستدعاء Refresh.

    Protected Overrides Sub OnLayout(ByVal levent As LayoutEventArgs)
        MyBase.OnLayout(levent)
    
        ' Repaint when the layout has changed.
        Me.Refresh()
    End Sub
    
    
    ' This method paints the lights around the border of the 
    ' control. It paints the top row first, followed by the
    ' right side, the bottom row, and the left side. The color
    ' of each light is determined by the IsLit method and
    ' depends on the light's position relative to the value
    ' of currentOffset.
    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        Dim g As Graphics = e.Graphics
        g.Clear(Me.BackColor)
    
        MyBase.OnPaint(e)
    
        ' If the control is large enough, draw some lights.
        If Me.Width > MaxLightSize AndAlso Me.Height > MaxLightSize Then
            ' The position of the next light will be incremented 
            ' by this value, which is equal to the sum of the
            ' light size and the space between two lights.
            Dim increment As Integer = _
            Me.lightSizeValue + Me.lightSpacingValue
    
            ' Compute the number of lights to be drawn along the
            ' horizontal edges of the control.
            Dim horizontalLights As Integer = _
            (Me.Width - increment) / increment
    
            ' Compute the number of lights to be drawn along the
            ' vertical edges of the control.
            Dim verticalLights As Integer = _
            (Me.Height - increment) / increment
    
            ' These local variables will be used to position and
            ' paint each light.
            Dim xPos As Integer = 0
            Dim yPos As Integer = 0
            Dim lightCounter As Integer = 0
            Dim brush As Brush
    
            ' Draw the top row of lights.
            Dim i As Integer
            For i = 0 To horizontalLights - 1
                brush = IIf(IsLit(lightCounter), Me.lightBrush, Me.darkBrush)
    
                DrawLight(g, brush, xPos, yPos)
    
                xPos += increment
                lightCounter += 1
            Next i
    
            ' Draw the lights flush with the right edge of the control.
            xPos = Me.Width - Me.lightSizeValue
    
            ' Draw the right column of lights.
            'Dim i As Integer
            For i = 0 To verticalLights - 1
                brush = IIf(IsLit(lightCounter), Me.lightBrush, Me.darkBrush)
    
                DrawLight(g, brush, xPos, yPos)
    
                yPos += increment
                lightCounter += 1
            Next i
    
            ' Draw the lights flush with the bottom edge of the control.
            yPos = Me.Height - Me.lightSizeValue
    
            ' Draw the bottom row of lights.
            'Dim i As Integer
            For i = 0 To horizontalLights - 1
                brush = IIf(IsLit(lightCounter), Me.lightBrush, Me.darkBrush)
    
                DrawLight(g, brush, xPos, yPos)
    
                xPos -= increment
                lightCounter += 1
            Next i
    
            ' Draw the lights flush with the left edge of the control.
            xPos = 0
    
            ' Draw the left column of lights.
            'Dim i As Integer
            For i = 0 To verticalLights - 1
                brush = IIf(IsLit(lightCounter), Me.lightBrush, Me.darkBrush)
    
                DrawLight(g, brush, xPos, yPos)
    
                yPos -= increment
                lightCounter += 1
            Next i
        End If
    End Sub
    
    protected override void OnLayout(LayoutEventArgs levent)
    {
        base.OnLayout(levent);
    
        // Repaint when the layout has changed.
        this.Refresh();
    }
    
    // This method paints the lights around the border of the 
    // control. It paints the top row first, followed by the
    // right side, the bottom row, and the left side. The color
    // of each light is determined by the IsLit method and
    // depends on the light's position relative to the value
    // of currentOffset.
    protected override void OnPaint(PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        g.Clear(this.BackColor);
    
        base.OnPaint(e);
    
        // If the control is large enough, draw some lights.
        if (this.Width > MaxLightSize &&
            this.Height > MaxLightSize)
        {
            // The position of the next light will be incremented 
            // by this value, which is equal to the sum of the
            // light size and the space between two lights.
            int increment =
                this.lightSizeValue + this.lightSpacingValue;
    
            // Compute the number of lights to be drawn along the
            // horizontal edges of the control.
            int horizontalLights =
                (this.Width - increment) / increment;
    
            // Compute the number of lights to be drawn along the
            // vertical edges of the control.
            int verticalLights =
                (this.Height - increment) / increment;
    
            // These local variables will be used to position and
            // paint each light.
            int xPos = 0;
            int yPos = 0;
            int lightCounter = 0;
            Brush brush;
    
            // Draw the top row of lights.
            for (int i = 0; i < horizontalLights; i++)
            {
                brush = IsLit(lightCounter) ? this.lightBrush : this.darkBrush;
    
                DrawLight(g, brush, xPos, yPos);
    
                xPos += increment;
                lightCounter++;
            }
    
            // Draw the lights flush with the right edge of the control.
            xPos = this.Width - this.lightSizeValue;
    
            // Draw the right column of lights.
            for (int i = 0; i < verticalLights; i++)
            {
                brush = IsLit(lightCounter) ? this.lightBrush : this.darkBrush;
    
                DrawLight(g, brush, xPos, yPos);
    
                yPos += increment;
                lightCounter++;
            }
    
            // Draw the lights flush with the bottom edge of the control.
            yPos = this.Height - this.lightSizeValue;
    
            // Draw the bottom row of lights.
            for (int i = 0; i < horizontalLights; i++)
            {
                brush = IsLit(lightCounter) ? this.lightBrush : this.darkBrush;
    
                DrawLight(g, brush, xPos, yPos);
    
                xPos -= increment;
                lightCounter++;
            }
    
            // Draw the lights flush with the left edge of the control.
            xPos = 0;
    
            // Draw the left column of lights.
            for (int i = 0; i < verticalLights; i++)
            {
                brush = IsLit(lightCounter) ? this.lightBrush : this.darkBrush;
    
                DrawLight(g, brush, xPos, yPos);
    
                yPos -= increment;
                lightCounter++;
            }
        }
    }
    

إنشاء Cusإلىm مصمم إلى الظل وخصائص عامل تصفية

MarqueeControlRootDesignerتوفر فئة التطبيق جذر مصمم. بالإضافة إلى رقم هو مصمم، والتي تعمل تشغيل MarqueeControl، ستكون بحاجة لمصمم مخصصة التي هو مقترنة بشكل خاص MarqueeBorderعنصر التحكم. Th هو مصمم يوفر سلوك المخصص الذي هو المناسب في سياق مصمم الجذر المخصصة.

تشغيل وجه الخصوص، MarqueeBorderDesigner"الظل" وقم بتصفية خصائص معينة تشغيل MarqueeBorderعنصر تحكم، تغيير بها التعامل مع بيئة التصميم.

تغييرها باستدعاء أسلوب استرجاع قيمة خاصية أحد مكونات هو تعرف باسم "النسخ المتماثل." يسمح مصمم لتعقب القيمة المعينة بواسطة مستخدم واختيارياً بتمرير القيمة إلى مكوّن الذي يتم تصميمه.

على سبيل المثال، Visibleو Enabledسوف تكون خصائص مظللاً MarqueeBorderDesigner، مما يمنع مستخدم من إجراء MarqueeBorderعنصر تحكم غير المرئي أو الذي تم تعطيله أثناء وقت التصميم.

يمكنك أيضا إضافة المصممين و إزالة الخصائص. تشغيل سبيل المثال، Paddingستتم تمت إزالته خاصية أثناء وقت التصميم، لأن MarqueeBorderعنصر تحكم برمجياً بتعيين المسافات البادئة تشغيل أساس الحجم الأضواء المحدد بواسطة LightSizeخاصية.

فئة Base ل MarqueeBorderDesignerهو ComponentDesigner، الذي يحتوي على الطرق التي يمكن تغيير السمات وخصائص الأحداث المعروضة عنصر تحكم وقت التصميم:

عند تغيير الواجهة العمومية من مكوّن استخدام هذه الطرق، يجب اتباع هذه القواعد:

  • إضافة عناصر أو إزالتها في PreFilterوظائف فقط

  • قم بتعديل عناصر موجود في PostFilterوظائف فقط

  • دوماً استدعاء تطبيق القاعدة الأولى في PreFilterوظائف

  • الاتصال دوماً الأساس تطبيق آخر في PostFilterوظائف

يتقيد إلى تضمن هذه القواعد أن مصممي الجميع في بيئة وقت التصميم لعرض متناسق لالجميع المكونات التي يتم تصميمها.

ComponentDesignerفئة يوفر قاموس لإدارة قيم خصائص نص مظلل، الذي relieves الحاجة إلى إنشاء مثيل معين متغيرات.

إلى إنشاء مصمم cusإلىm إلى خصائص الظل والتصفية

  1. انقر نقراً مزدوجاً فوق المجلد تصميم و إضافة فئة جديدة. تسمية الملف المصدر الأساس اسم "MarqueeBorderDesigner".

  2. بفتح MarqueeBorderDesignerمصدر ملف في محرر تعليمات برمجية. في الأعلى من الملف، قم باستيراد مساحات الاسم التالية:

    Imports System
    Imports System.Collections
    Imports System.ComponentModel
    Imports System.ComponentModel.Design
    Imports System.Diagnostics
    Imports System.Windows.Forms
    Imports System.Windows.Forms.Design
    
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;
    
  3. قم بتغيير التصريح MarqueeBorderDesignerإلى يورث ParentControlDesigner.

    لأن MarqueeBorderيمكن أن يحتوي على عنصر تحكم فرع عناصر التحكم، MarqueeBorderDesignerيرث من ParentControlDesigner، الذي يعالج الأصل-فرع تفاعل.

    Namespace MarqueeControlLibrary.Design
    
        <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
        Public Class MarqueeBorderDesigner
            Inherits ParentControlDesigner
    
    namespace MarqueeControlLibrary.Design
    {
        [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
        public class MarqueeBorderDesigner : ParentControlDesigner
        {
    
  4. يمنع التطبيق الأساسي ل PreFilterProperties.

    Protected Overrides Sub PreFilterProperties( _
    ByVal properties As IDictionary)
    
        MyBase.PreFilterProperties(properties)
    
        If properties.Contains("Padding") Then
            properties.Remove("Padding")
        End If
    
        properties("Visible") = _
        TypeDescriptor.CreateProperty(GetType(MarqueeBorderDesigner), _
        CType(properties("Visible"), PropertyDescriptor), _
        New Attribute(-1) {})
    
        properties("Enabled") = _
        TypeDescriptor.CreateProperty(GetType(MarqueeBorderDesigner), _
        CType(properties("Enabled"), _
        PropertyDescriptor), _
        New Attribute(-1) {})
    
    End Sub
    
    protected override void PreFilterProperties(IDictionary properties)
    {
        base.PreFilterProperties(properties);
    
        if (properties.Contains("Padding"))
        {
            properties.Remove("Padding");
        }
    
        properties["Visible"] = TypeDescriptor.CreateProperty(
            typeof(MarqueeBorderDesigner),
            (PropertyDescriptor)properties["Visible"],
            new Attribute[0]);
    
        properties["Enabled"] = TypeDescriptor.CreateProperty(
            typeof(MarqueeBorderDesigner),
            (PropertyDescriptor)properties["Enabled"],
            new Attribute[0]);
    }
    
  5. تطبيق Enabledو Visibleخصائص. هذه التطبيقات خلفية عنصر التحكم خصائص.

    Public Property Visible() As Boolean
        Get
            Return CBool(ShadowProperties("Visible"))
        End Get
        Set(ByVal Value As Boolean)
            Me.ShadowProperties("Visible") = Value
        End Set
    End Property
    
    
    Public Property Enabled() As Boolean
        Get
            Return CBool(ShadowProperties("Enabled"))
        End Get
        Set(ByVal Value As Boolean)
            Me.ShadowProperties("Enabled") = Value
        End Set
    End Property
    
    public bool Visible
    {
        get
        {
            return (bool)ShadowProperties["Visible"];
        }
        set
        {
            this.ShadowProperties["Visible"] = value;
        }
    }
    
    public bool Enabled
    {
        get
        {
            return (bool)ShadowProperties["Enabled"];
        }
        set
        {
            this.ShadowProperties["Enabled"] = value;
        }
    }
    

معالجة التغييرات في المكونات

MarqueeControlRootDesignerفئة يوفر تجربة وقت التصميم المخصص لجهاز MarqueeControlالمثيلات. معظم وظائف وقت التصميم هو موروثة من DocumentDesignerفئة؛ سيتم تعليمات برمجية تنفيذ التخصيصات الخاصة الثاني: معالجة التغييرات مكون وإضافة مصمم الأفعال.

تصميم المستخدمين الخاصة بهم MarqueeControlمثيلات، مصمم الجذر الخاص بك يقوم بتعقب التغييرات إلى MarqueeControlوعناصر التحكم التابعة الخاصة به. تصميم-الوقت يوفر بيئة مناسبة لخدمة، IComponentChangeService، لتغيير تعقب إلى الولاية مكوّن.

اكتساب مرجع إلى هذه الخدمة مع الاستعلام عن بيئة مع GetServiceالأسلوب. إذا كان الاستعلام ناجحاً، يمكن للمصمم يرفق معالج ل ComponentChangedحدث وتنفيذ أي مهام مطلوبة إلى الحفاظ على الولاية متناسقة في وقت التصميم.

في حالة من MarqueeControlRootDesignerفصل دراسي، سيتم الاتصال Refreshالأسلوب تشغيل كل IMarqueeWidgetكائن MarqueeControl. سيؤدي هذا الأمر IMarqueeWidgetالكائن إلى إعادة رسم نفسه مناسب عند مثل الخصائص الأصلية لها Sizeتغيرت.

لمعالجة التغييرات مكوّن

  1. بفتح MarqueeControlRootDesignerمصدر ملف في محرر تعليمات برمجية وتجاوز Initializeالأسلوب. الاتصال الأساس تطبيق ل Initializeوالاستعلام عن IComponentChangeService.

    MyBase.Initialize(component)
    
    Dim cs As IComponentChangeService = _
    CType(GetService(GetType(IComponentChangeService)), _
    IComponentChangeService)
    
    If (cs IsNot Nothing) Then
        AddHandler cs.ComponentChanged, AddressOf OnComponentChanged
    End If
    
    base.Initialize(component);
    
    IComponentChangeService cs =
        GetService(typeof(IComponentChangeService)) 
        as IComponentChangeService;
    
    if (cs != null)
    {
        cs.ComponentChanged +=
            new ComponentChangedEventHandler(OnComponentChanged);
    }
    
  2. تطبيق OnComponentChangedحدث. معالج اختبار نوع مكوّن المرسل، وإذا كان هو IMarqueeWidget، الاتصال بها Refreshالأسلوب.

    Private Sub OnComponentChanged( _
    ByVal sender As Object, _
    ByVal e As ComponentChangedEventArgs)
        If TypeOf e.Component Is IMarqueeWidget Then
            Me.Control.Refresh()
        End If
    End Sub
    
    private void OnComponentChanged(
        object sender,
        ComponentChangedEventArgs e)
    {
        if (e.Component is IMarqueeWidget)
        {
            this.Control.Refresh();
        }
    }
    

إضافة أفعال مصمم إلى مصمم Cusإلىm الخاص بك

فعل مصمم هو أمر قائمة مرتبطة بمعالج أحداث. مصمم الأفعال تضاف إلى قائمة المختصرة لمكون وقت التصميم. لمزيد من المعلومات، راجع DesignerVerb.

لن إضافة الثاني الأفعال المصمم لمصممي الخاص بك: اختبار تشغيل و إيقاف Test. ستمكنك هذه الأفعال إلى عرض وقت التشغيل سلوك MarqueeControlفي وقت التصميم. ستتم تمت الإضافة هذه الأفعال إلى MarqueeControlRootDesigner.

عند تشغيل اختبار هو استدعاء، معالج الأحداث فعل سيتم استدعاء StartMarqueeالأسلوب على MarqueeControl. عند إيقاف اختبار هو استدعاء، معالج الأحداث فعل سيتم استدعاء StopMarqueeالأسلوب تشغيل MarqueeControl. تطبيق StartMarqueeو StopMarqueeوظائف استدعاء هذه الأساليب تشغيل عناصر التحكم المضمنة التي تطبق IMarqueeWidget، لذا أي المتضمنة IMarqueeWidgetعناصر ستشارك أيضا في اختبار.

إلى إضافة أفعال مصمم إلى مصممي cusإلىm الخاص بك

  1. في MarqueeControlRootDesignerالفئة، إضافة معالجات الأحداث المسمى OnVerbRunTestو OnVerbStopTest.

    Private Sub OnVerbRunTest( _
    ByVal sender As Object, _
    ByVal e As EventArgs)
    
        Dim c As MarqueeControl = CType(Me.Control, MarqueeControl)
        c.Start()
    
    End Sub
    
    Private Sub OnVerbStopTest( _
    ByVal sender As Object, _
    ByVal e As EventArgs)
    
        Dim c As MarqueeControl = CType(Me.Control, MarqueeControl)
        c.Stop()
    
    End Sub
    
    private void OnVerbRunTest(object sender, EventArgs e)
    {
        MarqueeControl c = this.Control as MarqueeControl;
    
        c.Start();
    }
    
    private void OnVerbStopTest(object sender, EventArgs e)
    {
        MarqueeControl c = this.Control as MarqueeControl;
    
        c.Stop();
    }
    
  2. توصيل هذه معالجات الأحداث إلى الأفعال المصمم المطابقة الخاصة بهم. MarqueeControlRootDesignerيرثDesignerVerbCollectionمن به الأساس فئة. لن إنشاء جديدة اثنين DesignerVerbكائنات وإضافتها إلى هذه المجموعة في Initializeالأسلوب.

    Me.Verbs.Add(New DesignerVerb("Run Test", _
    New EventHandler(AddressOf OnVerbRunTest)))
    
    Me.Verbs.Add(New DesignerVerb("Stop Test", _
    New EventHandler(AddressOf OnVerbStopTest)))
    
    this.Verbs.Add(
        new DesignerVerb("Run Test",
        new EventHandler(OnVerbRunTest))
        );
    
    this.Verbs.Add(
        new DesignerVerb("Stop Test",
        new EventHandler(OnVerbStopTest))
        );
    

إنشاء UITypeEditor مخصص

عندما تقوم بإنشاء تجربة وقت التصميم مخصص للمستخدمين، فإنه هو غالباً مطلوباً لإنشاء إجراء مخصص باستخدام النافذة "خصائص". يمكن القيام بذلك بواسطة إنشاء UITypeEditor. لمزيد من المعلومات، راجع كيفية: إنشاء محرر نوع واجهة المستخدم.

MarqueeBorderعنصر تحكم الكشف عن عدة خصائص في خصائص نافذة. الثاني من هذه خصائص، MarqueeSpinDirection MarqueeLightShapeيتم تمثيلها بواسطة عمليات التعداد. لتوضيح استخدام نوع واجهة المستخدم محرر, MarqueeLightShapeسيكون مقترنة خاصية UITypeEditorفئة.

لإنشاء نوع واجهة مستخدم مخصصة محرر

  1. بفتح MarqueeBorderمصدر ملف في محرر تعليمات برمجية.

  2. في تعريف MarqueeBorderفئة، تقوم بتعريف فئة تسمى LightShapeEditorالتي مشتقة من UITypeEditor.

    ' This class demonstrates the use of a custom UITypeEditor. 
    ' It allows the MarqueeBorder control's LightShape property
    ' to be changed at design time using a customized UI element
    ' that is invoked by the Properties window. The UI is provided
    ' by the LightShapeSelectionControl class.
    Friend Class LightShapeEditor
        Inherits UITypeEditor
    
    // This class demonstrates the use of a custom UITypeEditor. 
    // It allows the MarqueeBorder control's LightShape property
    // to be changed at design time using a customized UI element
    // that is invoked by the Properties window. The UI is provided
    // by the LightShapeSelectionControl class.
    internal class LightShapeEditor : UITypeEditor
    {
    
  3. التصريح IWindowsFormsEditorServiceمتغير مثيل يسمى editorService.

    Private editorService As IWindowsFormsEditorService = Nothing
    
    private IWindowsFormsEditorService editorService = null;
    
  4. تجاوز الأسلوب GetEditStyle. بإرجاع هذا التطبيق DropDown، والتي تخبر بيئة تصميم كيفية إلى عرض LightShapeEditor.

            Public Overrides Function GetEditStyle( _
            ByVal context As System.ComponentModel.ITypeDescriptorContext) _
            As UITypeEditorEditStyle
                Return UITypeEditorEditStyle.DropDown
            End Function
    
    
    public override UITypeEditorEditStyle GetEditStyle(
    System.ComponentModel.ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.DropDown;
    }
    
  5. تجاوز الأسلوب EditValue. استعلامات تطبيق هذا تصميم بيئة لعنصر IWindowsFormsEditorServiceالكائن. في حالة نجاح ذلك، يقوم بإنشاء LightShapeSelectionControl. DropDownControlأسلوب هو استدعاء للبدء LightShapeEditor. يتم إرجاع القيمة التي يتم إرجاعها من هذا الاستدعاء إلى بيئة تصميم.

    Public Overrides Function EditValue( _
    ByVal context As ITypeDescriptorContext, _
    ByVal provider As IServiceProvider, _
    ByVal value As Object) As Object
        If (provider IsNot Nothing) Then
            editorService = _
            CType(provider.GetService(GetType(IWindowsFormsEditorService)), _
            IWindowsFormsEditorService)
        End If
    
        If (editorService IsNot Nothing) Then
            Dim selectionControl As _
            New LightShapeSelectionControl( _
            CType(value, MarqueeLightShape), _
            editorService)
    
            editorService.DropDownControl(selectionControl)
    
            value = selectionControl.LightShape
        End If
    
        Return value
    End Function
    
    public override object EditValue(
        ITypeDescriptorContext context,
        IServiceProvider provider,
        object value)
    {
        if (provider != null)
        {
            editorService =
                provider.GetService(
                typeof(IWindowsFormsEditorService))
                as IWindowsFormsEditorService;
        }
    
        if (editorService != null)
        {
            LightShapeSelectionControl selectionControl =
                new LightShapeSelectionControl(
                (MarqueeLightShape)value,
                editorService);
    
            editorService.DropDownControl(selectionControl);
    
            value = selectionControl.LightShape;
        }
    
        return value;
    }
    

قم بإنشاء عنصر تحكم عرض لجهاز UITypeEditor مخصص

  1. MarqueeLightShapeيدعم خاصية الثاني أنواع الأشكال فاتح: Square وCircle يتم إنشاء عنصر تحكم مخصص يستخدم فقط من أجل عرض هذه قيم بشكل رسومي نافذة الخصائص. هذا المخصص عنصر تحكم سيتم استخدامها بواسطة جهاز UITypeEditorبالتفاعل مع الإطار خصائص.

إلى بإنشاء عنصر تحكم عرض لجهاز ediإلىr نوع واجهة المستخدم cusإلىm

  1. إضافة جديد UserControlالعنصر إلى MarqueeControlLibraryمشروع. قم بإعطاء مصدر جديد ملف اسم أساسي من "LightShapeSelectionControl".

  2. اسحب انتشار Panelعناصر التحكم من مربع أدوات التحكم إلى LightShapeSelectionControl. اسم themsquarePanelوcirclePanel. ترتيبها بجانب بواسطة الجانب. قم بتعيين Sizeخاصية لكل من Panelعناصر التحكم إلى (60، 60). التعيين Locationخاصية squarePanelالتحكم إلى (8، 10). التعيين Locationخاصية circlePanelالتحكم إلى (80، 10). وأخيراً، تعيين Sizeخاصية LightShapeSelectionControlإلى (150، 80).

  3. بفتح LightShapeSelectionControlمصدر ملف في محرر تعليمات برمجية. في الأعلى ملف، قم باستيراد System.Windows.Forms.Designمساحة الاسم:

Imports System.Windows.Forms.Design
using System.Windows.Forms.Design;
  1. تطبيق Clickحدث معالجات squarePanelو circlePanelعناصر التحكم. استدعاء هذه الأساليب CloseDropDownإلى cusإلىm إنهاء UITypeEditor‏‏تحرير جلسة عمل.

    Private Sub squarePanel_Click( _
    ByVal sender As Object, _
    ByVal e As EventArgs)
    
        Me.lightShapeValue = MarqueeLightShape.Square
        Me.Invalidate(False)
        Me.editorService.CloseDropDown()
    
    End Sub
    
    
    Private Sub circlePanel_Click( _
    ByVal sender As Object, _
    ByVal e As EventArgs)
    
        Me.lightShapeValue = MarqueeLightShape.Circle
        Me.Invalidate(False)
        Me.editorService.CloseDropDown()
    
    End Sub
    
            private void squarePanel_Click(object sender, EventArgs e)
            {
                this.lightShapeValue = MarqueeLightShape.Square;
    
                this.Invalidate( false );
    
                this.editorService.CloseDropDown();
            }
    
            private void circlePanel_Click(object sender, EventArgs e)
            {
                this.lightShapeValue = MarqueeLightShape.Circle;
    
                this.Invalidate( false );
    
                this.editorService.CloseDropDown();
            }
    
  2. التصريح IWindowsFormsEditorServiceمتغير مثيل يسمى editorService.

Private editorService As IWindowsFormsEditorService
private IWindowsFormsEditorService editorService;
  1. التصريح MarqueeLightShapeمتغير مثيل يسمى lightShapeValue.

    Private lightShapeValue As MarqueeLightShape = MarqueeLightShape.Square
    
    private MarqueeLightShape lightShapeValue = MarqueeLightShape.Square;
    
  2. في LightShapeSelectionControlالمنشئ، يرفق Clickمعالجات حدث إلى squarePanelو circlePanelالخاصة بعناصر تحكم Clickالأحداث. أيضا، بتعريف التحميل الزائد الدالة الإنشائية الذي يعينه MarqueeLightShapeالقيمة من بيئة التصميم lightShapeValueالحقل.

    ' This constructor takes a MarqueeLightShape value from the
    ' design-time environment, which will be used to display
    ' the initial state.
     Public Sub New( _
     ByVal lightShape As MarqueeLightShape, _
     ByVal editorService As IWindowsFormsEditorService)
         ' This call is required by the Windows.Forms Form Designer.
         InitializeComponent()
    
         ' Cache the light shape value provided by the 
         ' design-time environment.
         Me.lightShapeValue = lightShape
    
         ' Cache the reference to the editor service.
         Me.editorService = editorService
    
         ' Handle the Click event for the two panels. 
         AddHandler Me.squarePanel.Click, AddressOf squarePanel_Click
         AddHandler Me.circlePanel.Click, AddressOf circlePanel_Click
     End Sub
    
            // This constructor takes a MarqueeLightShape value from the
            // design-time environment, which will be used to display
            // the initial state.
            public LightShapeSelectionControl( 
                MarqueeLightShape lightShape,
                IWindowsFormsEditorService editorService )
            {
                // This call is required by the designer.
                InitializeComponent();
    
                // Cache the light shape value provided by the 
                // design-time environment.
                this.lightShapeValue = lightShape;
    
                // Cache the reference to the editor service.
                this.editorService = editorService;
    
                // Handle the Click event for the two panels. 
                this.squarePanel.Click += new EventHandler(squarePanel_Click);
                this.circlePanel.Click += new EventHandler(circlePanel_Click);
            }
    
  3. في Disposeأسلوب، يفصل Clickمعالجات الأحداث.

    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
    
            ' Be sure to unhook event handlers
            ' to prevent "lapsed listener" leaks.
            RemoveHandler Me.squarePanel.Click, AddressOf squarePanel_Click
            RemoveHandler Me.circlePanel.Click, AddressOf circlePanel_Click
    
            If (components IsNot Nothing) Then
                components.Dispose()
            End If
    
        End If
        MyBase.Dispose(disposing)
    End Sub
    
            protected override void Dispose( bool disposing )
            {
                if( disposing )
                {
                    // Be sure to unhook event handlers
                    // to prevent "lapsed listener" leaks.
                    this.squarePanel.Click -= 
                        new EventHandler(squarePanel_Click);
                    this.circlePanel.Click -= 
                        new EventHandler(circlePanel_Click);
    
                    if(components != null)
                    {
                        components.Dispose();
                    }
                }
                base.Dispose( disposing );
            }
    
  4. في مستكشف الحلول، انقر فوق الزر عرض جميع الملفات. قم بفتح الملف LightShapeSelectionControl.مصمم.cs أو LightShapeSelectionControl.مصمم.vb، و إزالة تعريف افتراضي Disposeالأسلوب.

  5. تطبيق LightShapeخاصية.

    ' LightShape is the property for which this control provides
    ' a custom user interface in the Properties window.
    Public Property LightShape() As MarqueeLightShape
    
        Get
            Return Me.lightShapeValue
        End Get
    
        Set(ByVal Value As MarqueeLightShape)
            If Me.lightShapeValue <> Value Then
                Me.lightShapeValue = Value
            End If
        End Set
    
    End Property
    
            // LightShape is the property for which this control provides
            // a custom user interface in the Properties window.
            public MarqueeLightShape LightShape
            {
                get
                {
                    return this.lightShapeValue;
                }
    
                set
                {
                    if( this.lightShapeValue != value )
                    {
                        this.lightShapeValue = value;
                    }
                }
            }
    
  6. تجاوز الأسلوب OnPaint. سيتم رسم هذا التطبيق الممتلئ بمربع ودائرة. يميز أيضا القيمة المختارة برسم حد حول شكل واحد أو الآخر.

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        MyBase.OnPaint(e)
    
        Dim gCircle As Graphics = Me.circlePanel.CreateGraphics()
        Try
            Dim gSquare As Graphics = Me.squarePanel.CreateGraphics()
            Try
                ' Draw a filled square in the client area of
                ' the squarePanel control.
                gSquare.FillRectangle( _
                Brushes.Red, _
                0, _
                0, _
                Me.squarePanel.Width, _
                Me.squarePanel.Height)
    
                ' If the Square option has been selected, draw a 
                ' border inside the squarePanel.
                If Me.lightShapeValue = MarqueeLightShape.Square Then
                    gSquare.DrawRectangle( _
                    Pens.Black, _
                    0, _
                    0, _
                    Me.squarePanel.Width - 1, _
                    Me.squarePanel.Height - 1)
                End If
    
                ' Draw a filled circle in the client area of
                ' the circlePanel control.
                gCircle.Clear(Me.circlePanel.BackColor)
                gCircle.FillEllipse( _
                Brushes.Blue, _
                0, _
                0, _
                Me.circlePanel.Width, _
                Me.circlePanel.Height)
    
                ' If the Circle option has been selected, draw a 
                ' border inside the circlePanel.
                If Me.lightShapeValue = MarqueeLightShape.Circle Then
                    gCircle.DrawRectangle( _
                    Pens.Black, _
                    0, _
                    0, _
                    Me.circlePanel.Width - 1, _
                    Me.circlePanel.Height - 1)
                End If
            Finally
                gSquare.Dispose()
            End Try
        Finally
            gCircle.Dispose()
        End Try
    End Sub
    
            protected override void OnPaint(PaintEventArgs e)
            {
                base.OnPaint (e);
    
                using( 
                    Graphics gSquare = this.squarePanel.CreateGraphics(),
                    gCircle = this.circlePanel.CreateGraphics() )
                {   
                    // Draw a filled square in the client area of
                    // the squarePanel control.
                    gSquare.FillRectangle(
                        Brushes.Red, 
                        0,
                        0,
                        this.squarePanel.Width,
                        this.squarePanel.Height
                        );
    
                    // If the Square option has been selected, draw a 
                    // border inside the squarePanel.
                    if( this.lightShapeValue == MarqueeLightShape.Square )
                    {
                        gSquare.DrawRectangle( 
                            Pens.Black,
                            0,
                            0,
                            this.squarePanel.Width-1,
                            this.squarePanel.Height-1);
                    }
    
                    // Draw a filled circle in the client area of
                    // the circlePanel control.
                    gCircle.Clear( this.circlePanel.BackColor );
                    gCircle.FillEllipse( 
                        Brushes.Blue, 
                        0,
                        0,
                        this.circlePanel.Width, 
                        this.circlePanel.Height
                        );
    
                    // If the Circle option has been selected, draw a 
                    // border inside the circlePanel.
                    if( this.lightShapeValue == MarqueeLightShape.Circle )
                    {
                        gCircle.DrawRectangle( 
                            Pens.Black,
                            0,
                            0,
                            this.circlePanel.Width-1,
                            this.circlePanel.Height-1);
                    }
                }   
            }
    

اختبار جهاز عنصر تحكم مخصص في "مصمم"

عند هذه النقطة، يمكنك بنية MarqueeControlLibraryمشروع. اختبار التطبيق الخاص بك بإنشاء عنصر تحكم يرث من MarqueeControlالفئة و استخدامه تشغيل النموذج.

إلى إنشاء تنفيذ ما MarqueeControl مخصصة

  1. افتح DemoMarqueeControl في مصمم Windows Forms . يؤدي هذا إلى إنشاء مثيل من DemoMarqueeControlنوع و يعرض في مثيل MarqueeControlRootDesignerالنوع.

  2. في مربع أدوات التحكم، فتح علامة تبويب MarqueeControlLibrary مكونات. سوف تشاهد MarqueeBorderو MarqueeTextعناصر التحكم متوفر ل تحديد.

  3. اسحب مثيل MarqueeBorderعنصر تحكم إلى DemoMarqueeControlسطح التصميم. مرسى هذا MarqueeBorderعنصر تحكم إلى الأصل عنصر تحكم.

  4. اسحب مثيل MarqueeTextعنصر تحكم إلى DemoMarqueeControlسطح التصميم.

  5. قم ببناء الحل.

  6. بزر الماوس الأيمن فوق DemoMarqueeControlومن تحديد قائمة المختصرة خيار تشغيل اختبار من ل يبدأ رسم متحرك. انقر فوق الاختبار Sإلىp إلى sإلىp رسم متحرك.

  7. فتح Form1 في طريقة عرض التصميم.

  8. قم بوضع اثنين Buttonعناصر التحكم الموجودة نموذج. تسمية startButtonو stopButton، وتغيير Textقيم الخاصية إلى يبدأ والتوقف، على التوالي.

  9. تطبيق Clickحدث معالجات لكل منهما Buttonعناصر التحكم.

  10. في من مربع الأدوات، قم بفتح علامة تبويب MarqueeControlTest مكونات. سترى DemoMarqueeControlمتوفرة للتحديد.

  11. اسحب مثيل DemoMarqueeControlعلى من Form1 تصميم سطح.

  12. في Clickاستدعاء معالجات الأحداث، Startو Stopالأساليب تشغيل DemoMarqueeControl.

Private Sub startButton_Click(sender As Object, e As System.EventArgs)
    Me.demoMarqueeControl1.Start()
End Sub 'startButton_Click

Private Sub stopButton_Click(sender As Object, e As System.EventArgs)
Me.demoMarqueeControl1.Stop()
End Sub 'stopButton_Click
private void startButton_Click(object sender, System.EventArgs e)
{
    this.demoMarqueeControl1.Start();
}

private void stopButton_Click(object sender, System.EventArgs e)
{
    this.demoMarqueeControl1.Stop();
}
  1. قم بتعيين MarqueeControlTestمشروع كـ بدء تشغيل مشروع والتشغيل it. سوف تشاهد نموذج عرض الخاص بك DemoMarqueeControl. انقر فوق butإلىn ابدأ إلى بدء رسم متحرك. يجب أن تشاهد النص وميض وأضواء التنقل إلى الحد.

الخطوات التالية

MarqueeControlLibraryيوضح تطبيق بسيط من مخصص عناصر التحكم المقترنة مصممي. يمكنك جعل هذا النموذج المزيد تطورا بطرق متعددة:

  • قم بتغيير قيم الخصائص ل DemoMarqueeControlفي مصمم. قم بإضافة المزيد من MarqueBorderعناصر التحكم وإرساء لهم داخل الحالات الأصل الخاصة بها لإنشاء تأثير متداخل. التجربة مع إعدادات مختلفة ل UpdatePeriodوفي ضوء المتعلقة خصائص.

  • تأليف تطبيقات خاصة بك IMarqueeWidget. يمكنك، على سبيل المثال، إنشاء امض "مصابيح اشاره" أو علامة متحركة باستخدام صور متعددة.

  • يخصص الخبرة في وقت التصميم. قد حاولت تطبيق تظليل المزيد من الخصائص من Enabledو Visible، ويمكنك إضافة جديد الخصائص. إضافة أفعال المصمم الجديد إلى تبسيط المهام عام مثل إرساء عناصر التحكم التابعة.

  • ترخيص MarqueeControl. لمزيد من المعلومات، راجع كيفية: مكونات الترخيص وعناصر التحكم.

  • التحكم في كيفية إجراء تسلسل عناصر التحكم الخاصة بك وكيفية تعليمات برمجية هو التي تم إنشاؤها بالنسبة لهم. لمزيد من المعلومات، راجع إنشاء التعليمات البرمجية المصدر الحيوية و التصنيف.

راجع أيضًا:

المهام

كيفية: إنشاء عنصر تحكم نماذج Windows التي يأخذ ميزة ميزات وقت التصميم

المرجع

UserControl

ParentControlDesigner

DocumentDesigner

IRootDesigner

DesignerVerb

UITypeEditor

BackgroundWorker

موارد أخرى

توسيع دعم وقت التصميم

مصممو مخصصة

مكتبة شكل.NET: على مصمم نماذج