代码之家  ›  专栏  ›  技术社区  ›  Hazel へいぜる

ListView中的图像与BackColor属性不匹配

  •  3
  • Hazel へいぜる  · 技术社区  · 6 年前

    概述

    我目前正在为我的应用程序开发一个主题系统,允许用户选择明暗主题(类似于visual studio)。整个过程是非常直接的,这就是我如何改变 BackColor 财产 ListView 控件当前(尽管我尝试了一些失败的内联解决方案,例如仅设置 属性 列表视图 ListViewItem )

    击穿

    我有一个 ImageList 有6张图片;所有图片都有透明背景。每个图像都是一个不同颜色的玻璃球和一个阴影。我把这六幅图中的一幅给每个人 列表视图项 在我的内心 列表视图 (设置为 Details 视图)基于我从数据库中提取的状态的控件。

    一切都很好只要 列表视图 以及 列表视图项 图像被指定保持其 属性 属性设置为 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;
                }
            }
        }
    }
    

    我尝试添加一个方法来更新 属性 财产 列表视图 控制及其所有 列表视图项 对象,然后在 DrawItem DrawSubItem 事件(两者都不起作用);调用此方法来代替 Invalidate 方法 列表视图 ,在更改 ImageIndex 财产 列表视图项 ;我甚至试过打电话 使无效 在形式本身和重新画一切。

    我真的可以在这个问题上使用一些指导,因为到目前为止,其他的事情都很顺利;这是唯一让我绕圈子的问题。我在google上搜索了好几次,都没有发现任何与图片不一样的结果 属性 作为它的内含物 列表视图 列表视图项 . 也许我没有用正确的词来搜索,或者我是第一个抱怨这个问题的人;谁知道呢。如有任何帮助,我们将不胜感激。

    注释

    如果你觉得我遗漏了任何需要的信息,或者我对某些事情应该更清楚一些,请随时发表评论并让我知道,以便我可以为将来的读者更新文章的清晰度。

    新尝试(失败)

    • 尝试更改 列表视图 对象在设置 图像索引 财产。
    • 试用 OwnerDraw 以及 拖拉项目 事件来绘制图像。
    • 尝试创建 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);
    

    图像

    Desired Result

    这个 Current Result 其中绿点是图像,红点是背景问题,蓝框是 列表视图项 .

    1 回复  |  直到 6 年前
        1
  •  1
  •   TaW    6 年前

    展示个人 ListViewItem.BackColors 在你需要的图像下 业主抽签 否则 ListView.BackColor 将改为显示。但是你注意到在你的图像的半透明部分有丑陋的伪影。

    经过多次测试,我相信 ImageList 才是罪魁祸首。

    它似乎在应该是半平移像素的地方插入了灰色像素。完全透明的像素不受影响。

    这与它的属性无关。

    以下是业主图纸A的结果 ListView 有一次从一个 图像列表 一旦绘制了相同的图像,但直接从磁盘加载..:

    enter image description here enter 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);
    

    所以,如果你需要图像的半平移性,你就不能真正地将它们存储在 图像列表 .