ListView中的图像不匹配BackColor属性 [英] Images In ListView Don't Match BackColor Property
问题描述
概述
我目前正在为我的应用程序开发一个主题系统,允许用户选择浅色和深色主题(类似于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 theImageIndex
property. - Tried using
OwnerDraw
and theDrawItem
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
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屋!