如何将WinForms窗体Form1的ICO图标颜色修改为绿色?
问题现象
我下载了一个免费的红色图标,需要将它的颜色修改为绿色。我在Form1构造函数中编写了如下测试代码:
public Form1() { InitializeComponent(); var b = this.Icon.ToBitmap(); b.SetPixel(5, 5, Color.Green); pictureBox1.Image = b; }
运行后pictureBox1中显示的图标仍然为红色,效果参考截图:
界面左上角的小型红色图标是需要修改为绿色的Form1窗体图标;右侧用于测试、显示在pictureBox1中的大尺寸红色位图颜色也未发生变化,仍为红色。
问题原因
this.Icon.ToBitmap()返回的Bitmap和原图标资源的GDI句柄直接关联,直接对该对象调用SetPixel做的像素修改不会被持久化,渲染时还是会读取原始图标的像素数据。- 选择的修改坐标
(5,5)大概率位于图标边缘的透明区域,哪怕修改成功也看不到视觉变化,不会影响红色主体区域的显示。
修复方案
- 不要直接修改
Icon.ToBitmap()返回的原始对象,先创建独立的32位ARGB格式位图副本,绘制原始图标内容到新位图后再做像素修改,避免和原资源句柄绑定导致修改失效。 - 不要只修改单个透明边缘的像素点,如果要把图标整体的红色替换为绿色,遍历所有像素判断红色区域后统一替换即可;修改完成后既可以赋值给pictureBox显示,也可以转回Icon赋值给窗体的Icon属性,替换左上角的窗体图标。
可直接运行的参考代码:
public Form1() { InitializeComponent(); using (Bitmap originalBmp = this.Icon.ToBitmap()) { // 创建独立的可写位图副本 Bitmap modifiedBmp = new Bitmap(originalBmp.Width, originalBmp.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb); using (Graphics g = Graphics.FromImage(modifiedBmp)) { g.DrawImage(originalBmp, 0, 0, originalBmp.Width, originalBmp.Height); } // 遍历替换所有红色像素为绿色,阈值可根据图标实际的红色色值调整 for (int x = 0; x < modifiedBmp.Width; x++) { for (int y = 0; y < modifiedBmp.Height; y++) { Color px = modifiedBmp.GetPixel(x, y); if (px.R >= 220 && px.G <= 60 && px.B <= 60 && px.A > 0) { modifiedBmp.SetPixel(x, y, Color.Green); } } } // 给测试用pictureBox赋值 pictureBox1.Image = modifiedBmp; // 同时替换窗体左上角图标 IntPtr hIcon = modifiedBmp.GetHicon(); this.Icon = Icon.FromHandle(hIcon); } }
注意:如果你的图标尺寸较大,逐像素用
GetPixel/SetPixel修改性能较差,可以改用LockBits方式直接操作内存像素数据提升效率。
内容的提问来源于stack exchange,提问作者Daniel Lip
相关产品推荐
相关产品推荐

