Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > VB .NET > ComboBox с картинками


Автор: Spawn™Production® 4.1.2006, 22:16

Как известно, ComboBox не позволяет просто так добавлять перед элементами картинки, хотя порой очень хочется. Ну чтож, зато мы может собственноручно рисовать элементы выпадающего меню, так что сейчас я покажу, как силами .NET 2.0 сделать перед элементами ComboBox картинки.
Для примера сделаем аналог DriveListBox.
Для начала расположите на форме ComboBox и добавьте сюда же ImageList, где мы будем хранить картинки. Добавьте в ImageList 4 изображения - обычный диск, CD-Rom, Floppy, и неизвестное устройство. Теперь нужно изменить свойства ComboBox так, чтобы можно было обрабатывать события отрисовки элементов и они при этом имели смысл: свойству DrawMode задайте значение OwnerDrawFixed.
Теперь обратимся непосредственно к событиям формы.
При загрузке формы заполним наш ComboBox существующими в системе дисками:
Код

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim i As Integer
        'Заполняем ComboBox именами дисков
        For i = 0 To My.Computer.FileSystem.Drives.Count - 1
            ComboBox1.Items.Add(My.Computer.FileSystem.Drives(i).Name.ToString)
        Next
        'Добавляем к имени метку диска
        For i = 0 To My.Computer.FileSystem.Drives.Count - 1
        'Try приходится использовать, так как Floppy дисковод вызовет исключение, сли в нём ету дискеты.
            Try
                If My.Computer.FileSystem.Drives(i).VolumeLabel = "" Then
                Else
                    ComboBox1.Items.Item(i) += "  (" & My.Computer.FileSystem.Drives(i).VolumeLabel.ToString & ")"
                End If
            Catch ex As Exception
            End Try
        Next
    End Sub


Затем обработаем событие отрисовки элементов ComboBox.
Код

    Private Sub ComboBox1_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles ComboBox1.DrawItem
        Dim fnt As New Font(FontFamily.GenericSerif, 10, FontStyle.Regular) 'Шрифт для текста
        'Рисуем серый прямоугльничек...
        e.Graphics.DrawRectangle(New Pen(Color.White, 1), New Rectangle(e.Bounds.X, e.Bounds.Y, 209, 15))
        If e.Index <> -1 Then
            'Рисуем иконку диска.
            e.Graphics.DrawImage(ImageList1.Images(GetIndex(Mid(ComboBox1.Items.Item(e.Index).ToString, 1, 3))), e.Bounds.X, e.Bounds.Y)
            'Отрисовка в зависимости от состояния
            If e.State And DrawItemState.Selected Then
                e.Graphics.DrawString("     " & ComboBox1.Items.Item(e.Index).ToString, fnt, Brushes.Crimson, e.Bounds.X, e.Bounds.Y)
            Else
                e.Graphics.DrawString("     " & ComboBox1.Items.Item(e.Index).ToString, fnt, Brushes.Black, e.Bounds.X, e.Bounds.Y)
            End If
        End If
    End Sub
    'Функция на основе полученого имени диска вычисляет, какому индексу картинки в ImageList соответствует тип диска.
    Private Function GetIndex(ByVal d As String) As Integer
        Dim i, value As Integer
        For i = 0 To My.Computer.FileSystem.Drives.Count - 1
            With My.Computer.FileSystem.Drives.Item(i)
                If (.Name.ToString = d) Then 'Если имя перчисляемого диска соответствует переданному в функцию, то тогда вычисляем индекс.
                    Select Case .DriveType
                        Case IO.DriveType.Fixed
                            value = 0
                        Case IO.DriveType.CDRom
                            value = 1
                        Case IO.DriveType.Removable
                            value = 2
                        Case Else
                            value = 3
                    End Select
                End If
            End With
        Next
        GetIndex = value
    End Function

Автор: arilou 5.1.2006, 10:49
Давай подчистим код, переведем на C# и добавим в ФАК.

Автор: Spawn™Production® 5.1.2006, 15:59
Вот и перевод на C#. Прошу проверить предварительно, имхо я не знаю C# как таковой, а научился разбираться в нём только немного.

Код

        private void Form1_Load (System.Object sender, System.EventArgs e)
        {
            int i;
            //Заполняем ComboBox именами дисков
            for (i = 0; i <= System.Convert.ToInt32(System.IO.DriveInfo.GetDrives()) - 1; i++)
            {
                ComboBox1.Items.Add(System.IO.DriveInfo.GetDrives(i).Name.ToString());
            }
            //Добавляем к имени метку диска
            for (i = 0; i <= System.Convert.ToInt32(System.IO.DriveInfo.GetDrives()) - 1; i++)
            {
                //Try приходится использовать, так как Floppy дисковод вызовет исключение, сли в нём ету дискеты.
                try
                {
                    if (System.IO.DriveInfo.GetDrives(i).VolumeLabel == "")
                    {
                    }
                    else
                    {
                        ComboBox1.Items[i] += "  (" + System.IO.DriveInfo.GetDrives(i).VolumeLabel.ToString() + ")";
                    }
                }
                catch (Exception)
                {
                }
            }
        }



Код

        private void ComboBox1_DrawItem (object sender, System.Windows.Forms.DrawItemEventArgs e)
        {
            Font fnt = new Font(FontFamily.GenericSerif, 10, FontStyle.Regular); //Шрифт для текста С‚екста
            //Рисуем серый прямоугльничек...
            e.Graphics.DrawRectangle(new Pen(Color.White, 1), new Rectangle(e.Bounds.X, e.Bounds.Y, 209, 15));
            if (e.Index != - 1)
            {
                //Рисуем иконку диска.
                e.Graphics.DrawImage(ImageList1.Images[GetIndex(Strings.Mid(ComboBox1.Items[e.Index].ToString(), 1, 3))], e.Bounds.X, e.Bounds.Y);
                //Отрисовка в зависимости от состояния
                if (System.Convert.ToBoolean(e.State) && System.Convert.ToBoolean(DrawItemState.Selected))
                {
                    e.Graphics.DrawString("     " + ComboBox1.Items[e.Index].ToString(), fnt, Brushes.Crimson, e.Bounds.X, e.Bounds.Y);
                }
                else
                {
                    e.Graphics.DrawString("     " + ComboBox1.Items[e.Index].ToString(), fnt, Brushes.Black, e.Bounds.X, e.Bounds.Y);
                }
            }
        }
        //Функция на основе полученого имени диска вычисляет, какому индексу картинки в ImageList соответствует тип диска.
        private int GetIndex(string d)
        {
            int returnValue;
            int i;
            int value;
            for (i = 0; i <= System.Convert.ToInt32(System.IO.DriveInfo.GetDrives()) - 1; i++)
            {
                System.IO.DriveInfo with_1 = System.IO.DriveInfo.GetDrives(i);
                if (with_1.Name.ToString() == d) //Если имя перчисляемого диска соответствует переданному в функцию, то тогда вычисляем индекс.
                {
                    switch (with_1.DriveType)
                    {
                        case System.IO.DriveType.Fixed:
                            
                            value = 0;
                            break;
                        case System.IO.DriveType.CDRom:
                            
                            value = 1;
                            break;
                        case System.IO.DriveType.Removable:
                            
                            value = 2;
                            break;
                        default:
                            value = 3;
                            break;
                    }
                }
            }
            returnValue = value;
            return returnValue;
        }

Автор: arilou 5.1.2006, 16:30
Я зарефакторю немного, а потом предлагаю тебе оформить это дело в виде контрола. Что думаешь?

Автор: Spawn™Production® 5.1.2006, 16:41
arilou, ok, так, думаю, даже удобнее будет.

Автор: Exception 13.1.2006, 10:59
http://vingrad.ru/NET-VBNET-002996

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)