Изображения в ListView не совпадают с свойством BackColor - PullRequest
0 голосов
/ 04 июня 2018

Обзор

В настоящее время я работаю над системой тем для своего приложения, позволяющей пользователям выбирать темные светлые и темные (аналогично Visual Studio).Весь процесс довольно прост, и вот как я в настоящее время изменяю свойство BackColor элемента управления ListView (хотя я пробовал пару встроенных решений, которые потерпели неудачу, таких как установка BackColor ListViewи ListViewItem).

Разбивка

У меня ImageList с 6 изображениями;все из которых имеют прозрачный фон.Каждое изображение состоит из стеклянного шарика разных цветов и тени.Я присваиваю одно из этих шести изображений каждому ListViewItem в пределах моего ListView (установленного на Details view) элемента управления на основе статуса, который я получаю из своей базы данных.

Все отлично работает, пока ListView и ListViewItem, которому назначено изображение, сохраняет свойству BackColor значение Color.Control.Если он меняется на любой другой цвет (зеленый, серый, синий, красный и т. Д.);тогда задний цвет изображения не совпадает.Он продолжает сохранять цвет по умолчанию Color.Control.

Код темы

public static void ApplyTheme(Form f) {
    foreach (Control c in f.Controls) {
        if (c is MenuStrip)
            ThemeMenu((MenuStrip)c);
        else {
            ApplyStyles(c);
            if (c.Controls != null || c.Controls.Count > 0)
                RecurseChildControls(c);
        }
    }
}
public static void RecurseChildControls(Control parent) {
    foreach (Control child in parent.Controls) {
        ApplyStyles(child)

        if (child.Controls != null || child.Controls.Count > 0)
            RecurseChildControls(child);
    }
}
public static void ApplyStyles(Control c) {
    if (c is Button) {
        Button b = (Button)c;
        b.FlatStyle = FlatStyle.Flat;
        b.FlatAppearance.BorderSize = 0;
    }
    if (c is RoundedPanel || c is PictureBox) {
        // Do nothing.
    } else {
        if (c is Label) {
            if (c.Parent is RoundedPanel) {
                // Do nothing.
            } else {
                c.BackColor = BackColor;
                c.ForeColor = ForeColor;
            }
        } else {
            c.BackColor = BackColor;
            c.ForeColor = ForeColor;
        }

        if (c is ListView) {
            ListView lv = (ListView)c;
            if (Style = Themes.Dark)
                lv.GridLines = false;

            foreach (ListViewItem lvi in lv.Items) {
                lvi.BackColor = BackColor;
                lvi.ForeColor = ForeColor;
            }
        }
    }
}

Я попытался добавить один метод для обновлениясвойство BackColor элемента управления ListView и всех его объектов ListViewItem, затем я вызвал этот метод для событий DrawItem и DrawSubItem (ни один не работал);вызвал этот метод вместо Invalidate метода ListView, вызвал этот метод сразу после изменения свойства ImageIndex a ListViewItem;Я даже пытался вызвать Invalidate на самой форме и перерисовать все.

Я мог бы действительно использовать некоторые рекомендации по этому вопросу, так как все остальное пока работает отлично;это единственная проблема, которая заставляет меня вращаться по кругу.Я просматривал Google несколько раз и никогда не находил никаких результатов, связанных с тем, что изображение не имеет BackColor, содержащее ListView или ListViewItem.Возможно, я не выполняю поиск с правильными терминами, или, может быть, я первый, кто пожаловался на эту проблему;кто знает.Любая помощь приветствуется.

ПРИМЕЧАНИЕ

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

Новые попытки (сбои)

  • Попытка изменить цвет фона объекта ListView до (и после) установки свойства ImageIndex.
  • Попытка использовать OwnerDraw и событие DrawItem для рисования изображения.
  • Попытка создания Bitmap исходного изображения с указанным цветом фона, как показано ниже

Код попытки

// Bullet 2
e.Graphics.DrawImage(Image, Rectangle);

// Bullet 3
Rectangle r = new Rectangle(0, e.Bounds.Y, 16, 16);
Image I = imageList1.Images[e.Item.ImageIndex];
Bitmap b = new Bitmap(i.Width, i.Height);
using (Graphics g = Graphics.FromImage(b)) {
    g.Clear(Theme.BackColor);
    g.DrawImageUnscaledAndClipped(i, new Rectangle(Point.Empty, i.Size));
}
e.Graphics.DrawImage(b, r);

Изображения

Желаемый результат

Текущий результат где зеленыйточка - это изображение, красная точка - это проблема с фоном, а синяя рамка - ListViewItem.

1 Ответ

0 голосов
/ 05 июня 2018

Чтобы показать отдельного человека ListViewItem.BackColors под изображениями, вам нужно владелец-розыгрыш , иначе вместо этого будет отображаться ListView.BackColor.Но вы заметили уродливые артефакты в полупрозрачных частях ваших изображений.

После многочисленных испытаний я считаю, что ImageList является виновником.

Кажется, чтобы вставить серые пиксели там, где должны быть полупрозрачные пиксели.На полностью прозрачные пиксели это не влияет.

Это происходит независимо от его свойств.

Здесь приведены результаты рисования владельцем ListView один раз с изображением из ImageList и один раз при рисованиито же изображение, но загруженное непосредственно с диска ..:

enter image description hereenter image description here

Вы, конечно, можете видеть, какой есть какой ..

Изображение представляет собой желтый шарик на прозрачном фоне с полупрозрачным ореолом и двумя полупрозрачными отверстиями.

Код чертежа в событии ListView.DrawItem такой же:

e.DrawBackground();
e.DrawText();
Rectangle rect = new Rectangle(0, e.Bounds.Y, 32, 16);

Bitmap bmp1 = (Bitmap)imageList1.Images[e.Item.ImageIndex];
Bitmap bmp2 = (Bitmap)Bitmap.FromFile("filepath.png");

e.Graphics.DrawImage(bmp1_OR_bmp2, rect);

Так что, если вам нужна полупрозрачность изображений, вы не сможете сохранить их в ImageList.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...