ListView中的图像不匹配BackColor属性 [英] Images In ListView Don't Match BackColor Property

查看:77
本文介绍了ListView中的图像不匹配BackColor属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

概述

我目前正在为我的应用程序开发一个主题系统,允许用户选择浅色和深色主题(类似于Visual Studio).整个过程非常简单,这就是我现在更改 ListView 控件的 BackColor 属性的方式(尽管我已经尝试了一些失败的内联解决方案,例如设置 ListView ListViewItem BackColor .

故障

我有一个包含6张图片的 ImageList ;所有这些都有透明的背景.每个图像都是不同颜色的玻璃球和阴影的图像.我根据从数据库中提取的状态,将这六个图像之一分配给我的 ListView (设置为 Details 视图)控件中的每个 ListViewItem

只要将图像指定的 ListView ListViewItem 保持其 BackColor 属性设置为 Color,一切都可以正常工作.Control .如果更改为任何其他颜色(绿色,灰色,蓝色,红色等);则图像的底色不匹配.它继续保留默认的 Color.Control 颜色.

主题代码

  public static void ApplyTheme(Form f){foreach(f.Controls中的控件c){如果(c是MenuStrip)ThemeMenu((MenuStrip)c);别的 {ApplyStyles(c);如果(c.Controls!= null || c.Controls.Count> 0)RecurseChildControls(c);}}}公共静态无效RecurseChildControls(控制父级){foreach(parent.Controls中的控制子项){ApplyStyles(子级)if(child.Controls!= null || child.Controls.Count> 0)RecurseChildControls(child);}}公共静态无效的ApplyStyles(Control c){如果(c是Button){按钮b =(按钮)c;b.FlatStyle = FlatStyle.Flat;b.FlatAppearance.BorderSize = 0;}如果(c是RoundedPanel || c是PictureBox){//没做什么.} 别的 {如果(c是Label){if(c.Parent是RoundedPanel){//没做什么.} 别的 {c.BackColor = BackColor;c.ForeColor =前景色;}} 别的 {c.BackColor = BackColor;c.ForeColor =前景色;}如果(c是ListView){ListView lv =(ListView)c;如果(样式= Themes.Dark)lv.GridLines = false;foreach(lv.Items中的ListViewItem lvi){lvi.BackColor = BackColor;lvi.ForeColor = ForeColor;}}}} 

我尝试添加一种方法来更新 ListView 控件及其所有 ListViewItem 对象的 BackColor 属性,然后在 DrawItem DrawSubItem 事件上调用了此方法(均无效);在更改 ListViewItem <的 ImageIndex 属性之后立即调用此方法,以代替 ListView Invalidate 方法./code>;我什至尝试过在表单本身上调用 Invalidate 并重新绘制所有内容.

我真的可以在这方面使用一些指导,因为到目前为止其他所有工作都很好.这是让我转圈的唯一问题.我已经浏览过Google好几次了,但从未找到与该图像所包含的 ListView ListViewItem 相同的 BackColor 图像相关的结果.也许我没有以正确的词条进行搜索,或者也许我是第一个抱怨这个问题的人.谁知道.感谢您的帮助.

注意

如果您觉得我没有任何需要的信息,或者在某些事情上我应该更加清楚,请随时发表评论并告知我,以便我为以后的读者更新该文章的清晰度.

新的尝试(失败)

  • 尝试在设置 ImageIndex 属性之前和之后更改 ListView 对象的背景颜色.
  • 尝试使用 OwnerDraw DrawItem 事件绘制图像.
  • 尝试使用以下指定的背景色为原始图像创建位图

尝试密码

 //项目符号2e.Graphics.DrawImage(Image,Rectangle);//项目符号3矩形r =新矩形(0,e.Bounds.Y,16,16);图片I = imageList1.Images [e.Item.ImageIndex];位图b =新位图(i.Width,i.Height);使用(图形g = Graphics.FromImage(b)){g.Clear(Theme.BackColor);g.DrawImageUnscaledAndClipped(i,new Rectangle(Point.Empty,i.Size));}e.Graphics.DrawImage(b,r); 

图片

您肯定可以看到哪个..

图像是透明背景上的黄色斑点,带有一个半透明的光晕和两个半透明的孔.

ListView.DrawItem 事件中的绘图代码是相同的:

  e.DrawBackground();e.DrawText();Rectangle rect = new Rectangle(0,e.Bounds.Y,32,16);位图bmp1 =(位图)imageList1.Images [e.Item.ImageIndex];位图bmp2 =(位图)Bitmap.FromFile("filepath.png");e.Graphics.DrawImage(bmp1_OR_bmp2,rect); 

因此,如果您需要图像中的半透明性,则不能真正将它们存储在 ImageList 中.

Overview

I am currently working on a theme system for my application allowing Light and Dark themes for users to choose from (similar to visual studio). The entire process is pretty straight forward and this is how I am changing the BackColor property of the ListView control currently (though I have tried a couple inline solutions that failed such as just setting the BackColor of the ListView and ListViewItem).

Breakdown

I have an ImageList with 6 images; all of which have transparent backgrounds. Each image is of a glass ball of different colors and a drop shadow. I assign one of these six images to each ListViewItem within my ListView (set to Details view) control based on the status I pull from my database.

Everything works great so long as the ListView and the ListViewItem the image is assigned to keeps its BackColor property set to Color.Control. If it changes to any other color (green, gray, blue, red, etc.); then the back color of the image does not match. It continues to retain the default Color.Control color.

Theme Code

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;
            }
        }
    }
}

I've tried adding a single method to update the BackColor property of the ListView control and all of its ListViewItem objects, I then called this method on the DrawItem and DrawSubItem events (neither worked); called this method in place of the Invalidate method of the ListView, called this method right after changing the ImageIndex property of a ListViewItem; I've even tried calling Invalidate on the form itself and re-painting everything.

I could really use some guidance on this one since everything else is working out just fine so far; this is the only issue that has me spinning in circles. I've looked through Google several times and never find any results related to the image not having the same BackColor as its containing ListView or ListViewItem. Maybe I'm not performing the search with the right terms, or maybe I'm the first to complain about this issue; who knows. Any help is appreciated.

NOTE

If you feel I left out any needed information, or if I should be any clearer on certain things, feel free to comment and let me know so that I can update the clarity of the post for future readers.

New Attempts (Failures)

  • Tried changing the background color of the ListView object before (and after) setting the ImageIndex property.
  • Tried using OwnerDraw and the DrawItem event to draw the image.
  • Tried creating a Bitmap of the original image with a specified background color as below

Attempt Code

// 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);

Images

Desired Result

The Current Result where the green dot is the image, the red dot is the background issue, and the blue box is the ListViewItem.

解决方案

To show the individual ListViewItem.BackColors under the images you need to owner-draw or else the ListView.BackColor will show instead. But you noticed ugly artifacts in the semi-transparent portions of your images.

After numerous tests I believe that ImageList is the culprit.

It seems to insert greyed pixels where semi-tranparent pixels ought to be. Fully transparent pixels are not affected.

This happens independently of its properties.

Here are results of owner-drawing a ListView once with an image from an ImageList and once drawing the same image, but loaded directly from disk..:

You surely can see which is which..

The image is a yellow blob on transparent background with a semi-transparent halo and two semi-transparent holes.

The drawing code in the ListView.DrawItem event is the same:

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);

So, if you need semi-tranparency in images you can't really store them in an ImageList.

这篇关于ListView中的图像不匹配BackColor属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆