SO WIRD'S GEMACHT: Erstellen Sie einen Besitzer gezeichnete Listenfeld

Dieser Dokumentation für die Vorschau nur ist und in späteren Versionen geändert. Leere Themen wurden als Platzhalter eingefügt.]

Sie können ein Ownerdrawn-Listenfeld mit dem .NET Compact Framework erstellen, obwohl nicht so einfach wie mit dem vollständigen .NET Framework. .NET Compact Framework unterstützt nicht die DrawMode, DrawItem, und andere Zeichnung Mitglieder für Listen- und andere Steuerelemente, aber Sie können diese Funktionalität programmieren. In diesem Beispiel stellt eine benutzerdefinierte Steuerelement-Klasse, um ein Ownerdrawn-Listenfeld zu erstellen, und das Steuerelement als Listenfeld zum Auswählen von Schriftarten implementiert.

Dieses Beispiel enthält eine Basisklasse OwnerDrawnListBox, von dem FontListBox abgeleitet ist. OwnerDrawnListBox-Kernfunktionen gehören:

  • Dient, dass die vertikale Bildlaufleiste, ein Array mit der Elemente und eine Bitmap für das Listenfeld zu erstellen.

  • Stellt eine Element-Höhe-Eigenschaft und bestimmt, wie viele Elemente erhält die Höhe des Steuerelements gezeichnet werden können.

  • Stellt eine SelectedIndex-Eigenschaft, die das ausgewählte Element durch aktuellen Bildlaufleiste, Elementhöhe und Mauszeiger Koordinatenwerte bestimmt.

  • Stellt ein SelectedIndexChanged-Ereignis bereit.

  • Stellt die Sichtbarkeit der Elemente sicher.

  • Wird der Bildlauf-Leiste entfernt, wenn nicht benötigt.

  • Tastatur-Vorgang enthält, mit den nach oben und unten Navigationstasten.

FontListBox -Klasse erbt von OwnerDrawnListBox. Die Implementierungen und Techniken zählen:

  • Bestimmt die Höhe des entsprechenden Elements.

  • Zeichnet die Elemente, mit dem ausgewählten Element als markiert, gezeichnet mithilfe einer überschriebenen OnPaint-Methode. Um Flimmern zu vermeiden, zeigt diese Methode das Steuerelement nicht an, bis alle grafischen Features gezeichnet werden.

  • Stellt die SelectedFaceName-Eigenschaft bereit, mit dem Namen der ausgewählten Schriftart.

Das Formular, DrawFontList, geschieht Folgendes:

  • Erstellt eine neue Instanz der FontListBox, und fügt es der Controls-Auflistung hinzu.

  • Fügt einen Ereignishandler für das SelectedIndexChanged-Ereignis hinzu.

  • FontListBox mit einer Liste von Schriftarten füllt.

  • Stellt Bezeichnungen zum Anzeigen von im Beispiel der ausgewählten Schriftart bereit.

Um einen Besitzer gezeichneten Listenfeld zu erstellen

  1. Fügen der benutzerdefinierten Steuerelementklasse OwnerDrawnListBox Ihrem Projekt hinzu.

                                ' Base custom control for DrawFontList
                                Class OwnerDrawnListBox
        Inherits Control
        PrivateConst SCROLL_WIDTH AsInteger = 20
        Private itemH AsInteger = -1
        Private selIndex AsInteger = -1
    
        Private offScreenBitmap As Bitmap
        Private vs As VScrollBar
        Private itemsAList As ArrayList
    
    
        PublicSubNew()
            Me.vs = New VScrollBar
            Me.vs.Parent = MeMe.vs.Visible = FalseMe.vs.SmallChange = 1
            AddHandlerMe.vs.ValueChanged, AddressOfMe.ScrollValueChanged
    
            Me.itemsAList = New ArrayList
        EndSubPublicReadOnlyProperty Items() As ArrayList
            GetReturnMe.itemsAList
            EndGetEndPropertyProtectedReadOnlyProperty OffScreen() As Bitmap
            GetReturnMe.offScreenBitmap
            EndGetEndPropertyProtectedReadOnlyProperty VScrollBar() As VScrollBar
            GetReturnMe.vs
            EndGetEndPropertyFriendEvent SelectedIndexChanged As EventHandler
    
    
        ProtectedOverridableSub OnSelectedIndexChanged(ByVal e As EventArgs)
            RaiseEvent SelectedIndexChanged(Me, e)
        EndSubProtectedOverridesSub OnMouseDown(ByVal e As MouseEventArgs)
            Me.SelectedIndex = Me.vs.Value + e.Y / Me.ItemHeight
    
            ' Invalidate the control so we can draw the item as selected.Me.Refresh()
        EndSub
        ' Get or set index of selected item.PublicProperty SelectedIndex() AsIntegerGetReturnMe.selIndex
            EndGetSet(ByVal Value AsInteger)
                Me.selIndex = Value
    
                RaiseEvent SelectedIndexChanged(Me, Nothing)
            EndSetEndPropertyProtectedSub ScrollValueChanged(ByVal o AsObject, ByVal e As EventArgs)
            Me.Refresh()
        EndSubProtectedOverridableProperty ItemHeight() AsIntegerGetReturnMe.itemH
            EndGetSet(ByVal Value AsInteger)
                Me.itemH = Value
            EndSetEndProperty
    
        ' If the requested index is before the first visible index then set the    ' first item to be the requested index. If it is after the last visible    ' index, then set the last visible index to be the requested index.PublicSub EnsureVisible(ByVal index AsInteger)
            If index < Me.vs.Value ThenMe.vs.Value = index
                Me.Refresh()
            ElseIf index >= Me.vs.Value + Me.DrawCount ThenMe.vs.Value = index - Me.DrawCount + 1
                Me.Refresh()
            EndIfEndSub
    
        ' Need to set focus to the control when it     ' is clicked so that keyboard events occur.ProtectedOverridesSub OnClick(ByVal e As EventArgs)
            Me.Focus()
            MyBase.OnClick(e)
        EndSub
        ' Selected item moves when you use the keyboard up/down keys.ProtectedOverridesSub OnKeyDown(ByVal e As KeyEventArgs)
            SelectCase e.KeyCode
                Case Keys.Down
                    IfMe.SelectedIndex < Me.vs.Maximum ThenMe.SelectedIndex = Me.SelectedIndex + 1
                        EnsureVisible(Me.SelectedIndex + 1)
                        Me.Refresh()
                    EndIfCase Keys.Up
                    IfMe.SelectedIndex > Me.vs.Minimum ThenMe.SelectedIndex = Me.SelectedIndex - 1
                        EnsureVisible(Me.SelectedIndex - 1)
                        Me.Refresh()
                    EndIfCase Keys.PageDown
                    Me.SelectedIndex = Math.Min(Me.vs.Maximum, Me.SelectedIndex + Me.DrawCount)
                    EnsureVisible(Me.SelectedIndex)
                    Me.Refresh()
                Case Keys.PageUp
                    Me.SelectedIndex = Math.Max(Me.vs.Minimum, Me.SelectedIndex - Me.DrawCount)
                    EnsureVisible(Me.SelectedIndex)
                    Me.Refresh()
                Case Keys.Home
                    Me.SelectedIndex = 0
                    EnsureVisible(Me.SelectedIndex)
                    Me.Refresh()
                Case Keys.EndMe.SelectedIndex = Me.itemsAList.Count - 1
                    EnsureVisible(Me.SelectedIndex)
                    Me.Refresh()
            EndSelectMyBase.OnKeyDown(e)
        EndSub
        ' Calculate how many items we can draw given the height of the control.ProtectedReadOnlyProperty DrawCount() AsIntegerGetIfMe.vs.Value + Me.vs.LargeChange > Me.vs.Maximum ThenReturnMe.vs.Maximum - Me.vs.Value + 1
                ElseReturnMe.vs.LargeChange
                EndIfEndGetEndPropertyProtectedOverridesSub OnResize(ByVal e As EventArgs)
            Dim viewableItemCount AsInteger = Me.ClientSize.Height / Me.ItemHeight
    
            Me.vs.Bounds = New Rectangle(Me.ClientSize.Width - SCROLL_WIDTH, 0, SCROLL_WIDTH, Me.ClientSize.Height)
    
    
            ' Determine if scrollbars are neededIfMe.itemsAList.Count > viewableItemCount ThenMe.vs.Visible = TrueMe.vs.LargeChange = viewableItemCount
                Me.offScreenBitmap = New Bitmap(Me.ClientSize.Width - SCROLL_WIDTH - 1, Me.ClientSize.Height - 2)
            ElseMe.vs.Visible = FalseMe.vs.LargeChange = Me.itemsAList.Count
                Me.offScreenBitmap = New Bitmap(Me.ClientSize.Width - 1, Me.ClientSize.Height - 2)
            EndIfMe.vs.Maximum = Me.itemsAList.Count - 1
        EndSubEndClass
    
                                // Base custom control for DrawFontList
                                class OwnerDrawnListBox : Control
    {
        constint SCROLL_WIDTH = 20;
        int itemHeight         = -1;
        int selectedIndex      = -1;
    
        Bitmap offScreen;
        VScrollBar vs;
        ArrayList items;
    
        public OwnerDrawnListBox()
        {
            this.vs = new VScrollBar();
            this.vs.Parent      = this;
            this.vs.Visible     = false;
            this.vs.SmallChange = 1;
            this.vs.ValueChanged += new EventHandler(this.ScrollValueChanged);
    
            this.items = new ArrayList();
        }
    
        public ArrayList Items
        {
            get
            {
                returnthis.items;
            }
        }
    
        protected Bitmap OffScreen
        {
            get
            {
                returnthis.offScreen;
            }
        }
    
        protected VScrollBar VScrollBar
        {
            get
            {
                returnthis.vs;
            }
        }
    
        publicevent EventHandler SelectedIndexChanged;
    
        // Raise the SelectedIndexChanged eventprotectedvirtualvoid OnSelectedIndexChanged(EventArgs e)
        {
            if(this.SelectedIndexChanged != null)
                this.SelectedIndexChanged(this, e);
        }
    
        protectedoverridevoid OnMouseDown(MouseEventArgs e)
        {
            this.SelectedIndex = this.vs.Value + (e.Y / this.ItemHeight);
    
            // Invalidate the control so we can draw the item as selected.this.Refresh();
        }
    
        // Get or set index of selected item.publicint SelectedIndex
        {
            get
            {
                returnthis.selectedIndex;
            }
    
            set
            {
                this.selectedIndex = value;
    
                if (this.SelectedIndexChanged != null)
                    this.SelectedIndexChanged(this, EventArgs.Empty);
    
            }
        }
    
        protectedvoid ScrollValueChanged(object o, EventArgs e)
        {
            this.Refresh();
        }
    
        protectedvirtualint ItemHeight
        {
            get
            {
                returnthis.itemHeight;
            }
    
            set
            {
                this.itemHeight = value;
            }
        }
    
        // If the requested index is before the first visible index then set the// first item to be the requested index. If it is after the last visible// index, then set the last visible index to be the requested index.publicvoid EnsureVisible(int index)
        {
            if(index < this.vs.Value)
            {
                this.vs.Value = index;
                this.Refresh();
            }
            elseif(index >= this.vs.Value + this.DrawCount)
            {
                this.vs.Value = index - this.DrawCount + 1;
                this.Refresh();
            }
        }
    
    
        // Need to set focus to the control when it// is clicked so that keyboard events occur.protectedoverridevoid OnClick(EventArgs e)
        {
            this.Focus();
            base.OnClick(e);
        }
    
        // Selected item moves when you use the keyboard up/down keys.protectedoverridevoid OnKeyDown(KeyEventArgs e)
        {
            switch(e.KeyCode)
            {
                case Keys.Down:
                    if(this.SelectedIndex < this.vs.Maximum)
                    {
                        EnsureVisible(++this.SelectedIndex);
                        this.Refresh();
                    }
                    break;
                case Keys.Up:
                    if(this.SelectedIndex > this.vs.Minimum)
                    {
                        EnsureVisible(--this.SelectedIndex);
                        this.Refresh();
                    }
                    break;
                case Keys.PageDown:
                    this.SelectedIndex = Math.Min(this.vs.Maximum, this.SelectedIndex + this.DrawCount);
                    EnsureVisible(this.SelectedIndex);
                    this.Refresh();
                    break;
                case Keys.PageUp:
                    this.SelectedIndex = Math.Max(this.vs.Minimum, this.SelectedIndex - this.DrawCount);
                    EnsureVisible(this.SelectedIndex);
                    this.Refresh();
                    break;
                case Keys.Home:
                    this.SelectedIndex = 0;
                    EnsureVisible(this.SelectedIndex);
                    this.Refresh();
                    break;
                case Keys.End:
                    this.SelectedIndex = this.items.Count - 1;
                    EnsureVisible(this.SelectedIndex);
                    this.Refresh();
                    break;
            }
    
            base.OnKeyDown(e);
        }
    
        // Calculate how many items we can draw given the height of the control.protectedint DrawCount
        {
            get
            {
                if(this.vs.Value + this.vs.LargeChange > this.vs.Maximum)
                    returnthis.vs.Maximum - this.vs.Value + 1;
                elsereturnthis.vs.LargeChange;
            }
        }
    
        protectedoverridevoid OnResize(EventArgs e)
        {
            int viewableItemCount = this.ClientSize.Height / this.ItemHeight;
    
            this.vs.Bounds = new Rectangle(this.ClientSize.Width - SCROLL_WIDTH,
                0,
                SCROLL_WIDTH,
                this.ClientSize.Height);
    
    
            // Determine if scrollbars are neededif(this.items.Count > viewableItemCount)
            {
                this.vs.Visible = true;
                this.vs.LargeChange = viewableItemCount;
                this.offScreen = new Bitmap(this.ClientSize.Width - SCROLL_WIDTH - 1, this.ClientSize.Height - 2);
            }
            else
            {
                this.vs.Visible = false;
                this.vs.LargeChange = this.items.Count;
                this.offScreen = new Bitmap(this.ClientSize.Width - 1, this.ClientSize.Height - 2);
            }
    
            this.vs.Maximum = this.items.Count - 1;
        }
    }
    
  2. Fügen Sie die FontListBox -Klasse (die eine Implementierung von OwnerDrawnListBox ist hinzu) dem Projekt.

                                ' Derive an implementation of the
                                ' OwnerDrawnListBox class
                                Class FontListBox
        Inherits OwnerDrawnListBox
        PrivateConst FONT_SIZE AsInteger = 10
        PrivateConst DRAW_OFFSET AsInteger = 5
    
    
        PublicSubNew()
    
            ' Determine what the item height should be        ' by adding 30% padding after measuring        ' the letter A with the selected font.Dim g As Graphics = Me.CreateGraphics()
            Me.ItemHeight = Fix(g.MeasureString("A", Me.Font).Height * 1.3)
            g.Dispose()
        EndSub
        ' Return the name of the selected font.PublicReadOnlyProperty SelectedFaceName() AsStringGetReturnCStr(Me.Items(Me.SelectedIndex))
            EndGetEndProperty
    
        ' Determine what the text color should be    ' for the selected item drawn as highlightedFunction CalcTextColor(ByVal backgroundColor As Color) As Color
            If backgroundColor.Equals(Color.Empty) ThenReturn Color.Black
            EndIfDim sum AsInteger = backgroundColor.R + backgroundColor.G + backgroundColor.B
    
            If sum > 256 ThenReturn Color.Black
            ElseReturn Color.White
            EndIfEndFunctionProtectedOverridesSub OnPaint(ByVal e As PaintEventArgs)
            Dim font As Font
            Dim fontColor As Color
    
            ' The base class contains a bitmap, offScreen, for constructing        ' the control and is rendered when all items are populated.        ' This technique prevents flicker.Dim gOffScreen As Graphics = Graphics.FromImage(Me.OffScreen)
            gOffScreen.FillRectangle(New SolidBrush(Me.BackColor), Me.ClientRectangle)
    
            Dim itemTop AsInteger = 0
    
            ' Draw the fonts in the list.Dim n AsIntegerFor n = Me.VScrollBar.Value To (Me.VScrollBar.Value + DrawCount) - 1
                ' If the font name contains "dings" it needs to be displayed            ' in the list box with a readable font with the default font.IfCStr(Me.Items(n)).ToLower().IndexOf("dings") <> -1 Then
                    font = New Font(Me.Font.Name, FONT_SIZE, FontStyle.Regular)
                Else
                    font = New Font(CStr(Me.Items(n)), FONT_SIZE, FontStyle.Regular)
                EndIf            ' Draw the selected item to appear highlightedIf n = Me.SelectedIndex Then
                    gOffScreen.FillRectangle(New SolidBrush(SystemColors.Highlight), 1, itemTop + 1, Me.ClientSize.Width - IIf(Me.VScrollBar.Visible, Me.VScrollBar.Width, 2), Me.ItemHeight)
                    ' If the scroll bar is visible, subtract the scrollbar width                ' otherwise subtract 2 for the width of the rectangle
                    fontColor = CalcTextColor(SystemColors.Highlight)
                Else
                    fontColor = Me.ForeColor
                EndIf            ' Draw the item
                gOffScreen.DrawString(CStr(Me.Items(n)), font, New SolidBrush(fontColor), DRAW_OFFSET, itemTop)
                itemTop += Me.ItemHeight
            Next n
    
            ' Draw the list box
            e.Graphics.DrawImage(Me.OffScreen, 1, 1)
    
            gOffScreen.Dispose()
        EndSub
    
        ' Draws the external border around the control.ProtectedOverridesSub OnPaintBackground(ByVal e As PaintEventArgs)
            e.Graphics.DrawRectangle(New Pen(Color.Black), 0, 0, Me.ClientSize.Width - 1, Me.ClientSize.Height - 1)
        EndSubEndClass
    
                                // Derive an implementation of the
                                // OwnerDrawnListBox class
                                class FontListBox : OwnerDrawnListBox
    {
        constint FONT_SIZE    = 10;
        constint DRAW_OFFSET  = 5;
    
        public FontListBox()
        {
    
            // Determine what the item height should be// by adding 30% padding after measuring// the letter A with the selected font.
            Graphics g = this.CreateGraphics();
            this.ItemHeight = (int)(g.MeasureString("A", this.Font).Height * 1.3);
            g.Dispose();
        }
    
        // Return the name of the selected font.publicstring SelectedFaceName
        {
            get
            {
                return (string)this.Items[this.SelectedIndex];
            }
        }
    
        // Determine what the text color should be// for the selected item drawn as highlighted
        Color CalcTextColor(Color backgroundColor)
        {
            if(backgroundColor.Equals(Color.Empty))
                return Color.Black;
    
            int sum = backgroundColor.R + backgroundColor.G + backgroundColor.B;
    
            if(sum > 256)
                return Color.Black;
            elsereturn Color.White;
        }
    
        protectedoverridevoid OnPaint(PaintEventArgs e)
        {
            Font font;
            Color fontColor;
    
            // The base class contains a bitmap, offScreen, for constructing// the control and is rendered when all items are populated.// This technique prevents flicker.
            Graphics gOffScreen = Graphics.FromImage(this.OffScreen);
            gOffScreen.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);
    
            int itemTop = 0;
    
            // Draw the fonts in the list.for(int n = this.VScrollBar.Value; n < this.VScrollBar.Value + DrawCount; n++)
            {
                // If the font name contains "dings" it needs to be displayed
                // in the list box with a readable font with the default font.if(((string)this.Items[n]).ToLower().IndexOf("dings") != -1)
                    font = new Font(this.Font.Name, FONT_SIZE, FontStyle.Regular);
                else
                    font = new Font((string)this.Items[n], FONT_SIZE, FontStyle.Regular);
    
                // Draw the selected item to appear highlightedif(n == this.SelectedIndex)
                {
                    gOffScreen.FillRectangle(new SolidBrush(SystemColors.Highlight),
                        1,
                        itemTop + 1,
                        // If the scroll bar is visible, subtract the scrollbar width// otherwise subtract 2 for the width of the rectanglethis.ClientSize.Width - (this.VScrollBar.Visible ? this.VScrollBar.Width : 2),
                        this.ItemHeight);
                    fontColor = CalcTextColor(SystemColors.Highlight);
                }
                else
                    fontColor = this.ForeColor;
    
                // Draw the item
                gOffScreen.DrawString((string)this.Items[n], font, new SolidBrush(fontColor), DRAW_OFFSET, itemTop);
                itemTop += this.ItemHeight;
            }
    
            // Draw the list box
            e.Graphics.DrawImage(this.OffScreen, 1, 1);
    
            gOffScreen.Dispose();
        }
    
        // Draws the external border around the control.protectedoverridevoid OnPaintBackground(PaintEventArgs e)
        {
            e.Graphics.DrawRectangle(new Pen(Color.Black), 0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1);
        }
    }
    
  3. Fügen Sie im Formular zwei Label Steuerelemente hinzu, und nennen Sie Sie descLabel und sampleLabel;Letzteres wird ein FontListBox ausgewählten Schriftart Beispiel angezeigt.

  4. Erstellen Sie eine Instanz von FontListBox für das Formular.

  5. Fügen Sie den folgenden Code an den Konstruktor des Ereignisses Load für Formular.

                                ' Create a new instance of FontListBox.
    myListBox.Parent = Me
    ' Configure the event handler for the SelectedIndexChanged event. AddHandler myListBox.SelectedIndexChanged, AddressOfMe.SelectedIndexChanged
    
    ' Draw the bounds of the FontListBox.
    myListBox.Bounds = New Rectangle(5, 5, 150, 100)
    
    ' Add fonts to list, repeat the list 4 times' so that the scroll bar can be demonstrated.Dim n AsIntegerFor n = 0 To 3
        myListBox.Items.Add("Bookdings")
        myListBox.Items.Add("Courier New")
        myListBox.Items.Add("Frutiger Linotype")
        myListBox.Items.Add("Tahoma")
    Next n
    
    
    ' Labels to show the selected font from the list box. Assumes' instances of these labels have been declared for the form.
    descLabel.Parent = Me
    descLabel.Text = "Font Sample:"
    descLabel.Bounds = New Rectangle(10, myListBox.Bottom + 20, Me.ClientSize.Width - 10, 30)
    
    ' Assumes an instance sampleLabel is declared for the form.
    sampleLabel.Parent = Me
    sampleLabel.Bounds = New Rectangle(10, descLabel.Bottom, Me.ClientSize.Width - 10, 30)
    sampleLabel.Text = "AaBbCc 123"
    
                                // Create a new instance of FontListBox.
    box = new FontListBox();
    box.Parent = this;
    
    // Configure the event handler for the SelectedIndexChanged event.
    box.SelectedIndexChanged += new EventHandler(this.SelectedIndexChanged);
    
    // Draw the bounds of the FontListBox.
    box.Bounds = new Rectangle(5, 5, 150, 100);
    
    // Add fonts to list, repeat the list 4 times// so that the scroll bar can be demonstrated.for(int n = 0; n < 4; n++)
    {
        box.Items.Add("Bookdings");
        box.Items.Add("Courier New");
        box.Items.Add("Frutiger Linotype");
        box.Items.Add("Tahoma");
    }
    
    
    // Labels to show the selected font and a sample.
    Label desc = new Label();
    desc.Parent = this;
    desc.Text = "Font Sample:";
    desc.Bounds = new Rectangle(10, box.Bottom + 20, this.ClientSize.Width - 10, 30);
    
    sample = new Label();
    sample.Parent = this;
    sample.Bounds = new Rectangle(10, desc.Bottom, this.ClientSize.Width - 10, 30);
    sample.Text = "AaBbCc 123";
    
  6. Fügen Sie Code für die SelectedChangedEvent -Ereignis des Steuerelements FontListBox , dem die ausgewählte Schriftart in das Steuerelement sampleLabel angezeigt.

                                ' Event handler for SelectedIndexChanged to
                                ' display a sample of the selected font.
    
    ' Assumes that an instace of myListBox has been declared for the form.
                                Friend
                                Sub SelectedIndexChanged(ByVal o AsObject, ByVal e As EventArgs)
        sampleLabel.Font = New Font(myListBox.SelectedFaceName, 12, FontStyle.Regular)
    EndSub
    
                                // Event handler for SelectedIndexChanged to
                                // display a sample of the selected font.
                                private
                                void SelectedIndexChanged(object o, EventArgs e)
    {
        sample.Font = new Font(box.SelectedFaceName, 12, FontStyle.Regular);
    }
    

Kompilieren des Codes

In diesem Beispiel sind Verweise auf die folgenden Namespaces erforderlich:

Siehe auch

Konzepte

Benutzerdefinierte Control Development

.NET compact Framework Gewusst-wie-Themen