【发布时间】:2018-06-04 16:25:34
【问题描述】:
概述
我目前正在为我的应用程序开发一个主题系统,允许用户选择浅色和深色主题(类似于 Visual Studio)。整个过程非常简单,这就是我当前更改ListView 控件的BackColor 属性的方式(尽管我尝试了一些失败的内联解决方案,例如仅设置ListView 的BackColor和ListViewItem)。
细分
我有一个ImageList,有 6 张图片;所有这些都有透明的背景。每个图像都是一个不同颜色的玻璃球和一个投影。根据我从数据库中提取的状态,我将这六个图像中的一个分配给我的ListView(设置为Details 视图)控件中的每个ListViewItem。
只要分配图像的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;
}
}
}
}
我尝试添加一个方法来更新ListView 控件的BackColor 属性及其所有ListViewItem 对象,然后我在DrawItem 和DrawSubItem 事件上调用了这个方法(两者都没有)工作);调用此方法代替ListView 的Invalidate 方法,在更改ListViewItem 的ImageIndex 属性后立即调用此方法;我什至尝试在表单本身上调用Invalidate 并重新绘制所有内容。
我真的可以在这方面使用一些指导,因为到目前为止一切都很好;这是唯一让我绕圈子的问题。我已经通过谷歌浏览了好几次,但从来没有找到任何与图像相关的结果,它与包含ListView 或ListViewItem 的图像不具有相同的BackColor。也许我没有使用正确的术语进行搜索,或者我是第一个抱怨这个问题的人;谁知道。任何帮助表示赞赏。
注意
如果您觉得我遗漏了任何需要的信息,或者如果我应该对某些事情更清楚,请随时发表评论并告诉我,以便我可以为未来的读者更新帖子的清晰度。
新尝试(失败)
- 尝试在设置
ImageIndex属性之前(和之后)更改ListView对象的背景颜色。 - 尝试使用
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);
图片
Current Result,其中绿点是图片,红点是背景问题,蓝框是ListViewItem。
【问题讨论】:
-
欢迎您!这是一个写得很好的问题! - 我相信具有透明度的图像下方显示的背景颜色始终是 lv 背景色,无论 lvitems 有什么,除非您拥有它。然后通过调用 e.DrawBackground 将 lvi.backcolor 绘制在整个宽度上,包括空间图片..:
e.DrawBackground(); e.DrawText(); Rectangle rect = new Rectangle(0, e.Bounds.Y, 16, 16); e.Graphics.DrawImage(imageList1.Images[e.Item.ImageIndex],rect ); -
@TaW Hrmmm...所以我对您刚才所说的背景颜色理论进行了快速测试,但没有效果。现在要查看
OwnerDraw,我会发布更新。我认为具有透明度的图像不会像PictureBox控件那样反映底层容器控件的背景颜色。 -
@TaW 所以
OwnerDraw也是失败的。图片仍然保留着那可怕的Color.Control外观。 -
@TaW 我希望我可以,一切都在一台无法访问互联网的封闭机器上。我可以偶然查看一下 Google 图片上是否有任何内容。您是否使用
DrawItem事件来执行该绘制或其他操作? -
@TaW 似乎比它真正的价值要付出更多的努力;我想在这一点上它会归结为该方法的效率。我会四处寻找一些文章并尝试一下。
标签: c# winforms listview themes