Пользовательский ImageComboBox не всегда ведет себя одинаково

#c# #winforms #events #combobox

#c# #winforms #Мероприятия #combobox

Вопрос:

Я создал пользовательский comboBox интерфейс, который поддерживает изображения перед текстом элементов. Вот как это выглядит: ImageComboBox

Для этого я создал новый вызываемый элемент управления ImageComboBox , который хранится в dll файле, на который ссылается мой проект winforms.
Это ImageComboBox не что иное, как a ComboBox с DrawMode установленным значением DrawMode.OwnerDrawFixed и удерживающим a ImageList , который содержит все изображения для рисования. Существует a DrawItemEventHandler , который отвечает за рисование изображения и текста каждого элемента.

Я сталкиваюсь с проблемой с двумя пикселями, но запутанная часть заключается в том, что проблема возникает не всегда. Когда я создаю новый проект winforms и просто добавляю новый ImageComboBox , у меня нет проблемы. Когда я добавляю новый ImageComboBox в проект winforms, довольно продвинутый, возникает проблема — 9 раз из 10 раз (или что-то в этом роде).


Вот шаг, чтобы воспроизвести мою проблему с двумя пикселями:

  1. Когда я открываю форму, все в порядке:
    Первый шаг
  2. Когда я опускаю imageComboBox , все в порядке:
    Второй шаг
  3. Когда я навожу курсор на элемент, чтобы выбрать его, все в порядке:
    Третий шаг
  4. Когда я выбираю элемент, все в порядке:
    Четвертый шаг
  5. И когда я выпадаю imageComboBox , когда выбран элемент, возникает проблема: изображение перед выбранным элементом сдвигается на два пикселя справа, а текст сдвигается на один пиксель слева:
    Пятый шаг
    Давайте увеличим: Пятый шаг - увеличение
  6. И вот доказательство, что у меня иногда нет ошибки:
    Пятый шаг - нет ошибки
    Давайте снова увеличим масштаб:
    Пятый шаг - нет ошибки - увеличенный

Вот DrawItemEvent мой ImageComboBox :
( this._imageList это мой ImageList объект)

 private void OnDrawItem(object sender, DrawItemEventArgs e) {
    if (e.Index >= 0) {
        // If the current item is one in the comboBox

        // Compute the X location of the text to drawn
        int strLocationX = this._imageList.Images.Count > e.Index ?
                this._imageList.Images[e.Index].Width   1 :
                e.Bounds.X   1;

        // Get the displayed text of the current item
        String itemText = this.Items[e.Index].ToString();

        if (this.DroppedDown) {
            // If the comboBox is dropped down

            // Draw the blue rectangle
            e.DrawBackground();

            if (e.State == DrawItemState.ComboBoxEdit) {
                // If we are drawing the selected item

                // Draw the text
                e.Graphics.DrawString(itemText, this.Font, Brushes.Black, 
                    new Point(strLocationX   1, e.Bounds.Y   1));

                if (this._imageList.Images.Count > e.Index) {
                    // If we have an image available

                    // Draw the image
                    e.Graphics.DrawImage(this._imageList.Images[e.Index],
                        new Point(e.Bounds.X, e.Bounds.Y - 1));
                }

            } else {
                // If we are drawing one of the item in the drop down

                // Check if the item is being highlighted
                if (e.State.ToString().Contains(DrawItemState.Focus.ToString()) amp;amp;
                    e.State.ToString().Contains(DrawItemState.Selected.ToString())) {
                    // Draw the text in White
                    e.Graphics.DrawString(itemText, this.Font, Brushes.White, 
                        new Point(strLocationX, e.Bounds.Y   1));
                } else {
                    // Draw the text in Black
                    e.Graphics.DrawString(itemText, this.Font, Brushes.Black, 
                        new Point(strLocationX, e.Bounds.Y   1));
                }

                if (this._imageList.Images.Count > e.Index) {
                    // If we have an image available

                    // Draw the image
                    e.Graphics.DrawImage(this._imageList.Images[e.Index],
                        new Point(e.Bounds.X   2, e.Bounds.Y - 1));
                }
            }
        } else {
            // If the comboBox is not dropped down

            // Draw the text
            e.Graphics.DrawString(itemText, this.Font, Brushes.Black, 
                new Point(strLocationX   1, e.Bounds.Y   1));

            if (this._imageList.Images.Count > e.Index) {
                // If we have an image available

                // Draw the image
                e.Graphics.DrawImage(this._imageList.Images[e.Index],
                    new Point(e.Bounds.X, e.Bounds.Y - 1));
            }
        }
    }
}
  

С моей точки зрения, код должен быть правильным, но кажется, что иногда if условия не возвращают одинаковые результаты, тогда как я думаю, что так и должно быть.

Есть какие-либо подсказки о том, откуда может возникнуть эта проблема?

Ответ №1:

Найден ответ: код был неправильным, у меня было неправильное if условие в начале фрагмента (но я все еще не понимаю, почему ошибка иногда происходила, а иногда нет).

Я должен использовать:

 if (this.DroppedDown) {
    // If the comboBox is dropped down

    // Draw the blue rectangle
    e.DrawBackground();

    if (( e.State amp; DrawItemState.ComboBoxEdit ) == DrawItemState.ComboBoxEdit) {
        // If we are drawing the selected item

        // ...
  

вместо:

 if (this.DroppedDown) {
    // If the comboBox is dropped down

    // Draw the blue rectangle
    e.DrawBackground();

    if (e.State == DrawItemState.ComboBoxEdit) {
        // If we are drawing the selected item

        // ...