C# Winform 窗体美化(八、Icon)

八、Icon

之前 Winform 项目也有在 Icon 上遇到些问题(这里的 Icon 指的是 .ico 类型的文件),比如刚开始不知道怎么让自己的程序 Icon 和其他软件一样可以放大,还有放大之后在音量合成器中会出现比较奇葩的效果之类的问题,这里简单整理下,以后再有其他问题再补充。

1、C# 代码转换 Icon 格式

最开始写 Winform 程序的时候,程序图标都是从网上 down 的,因为那时候我下载了个精简版的ps cs3 里面不能保存 ico 文件,后来我找了个可以用 ps cs3 保存 ico 文件的插件,就可以保存 Ico 格式的文件了,最近突发奇想能不能用 C# 代码来转换 Icon 格式,这个例子在网上看过,有个网站可以将 Png 转换成 Ico,OK 既然有就可以试验一下。

网上最多的代码就是:

Bitmap iconBm = new Bitmap(oriImage, size);Icon icon = Icon.FromHandle(iconBm.GetHicon());//保存文件省略

这玩意儿确实能生成 Ico 格式的文件,但是这真的是个坑,因为生成的 Ico 是这样的:

网上有这种困扰的人很多,大致看了下原因是颜色位数的问题,那肯定的,颜色少的也太多了……

不过随后找到一个文章,完美的做好了转换,引用地址:http://www.cnblogs.com/ahdung/p/ConvertToIcon.html

Icon 文件说明:https://msdn.microsoft.com/en-us/library/ms997538.aspx

作者的方法原理是:先将image编码为png;再将png原样包装成一个icon。在这要谢谢作者提供的方法,提供了新思路,完美解决问题。

这里顺便一贴方法代码(Save 方法是我顺手补的……):

/// <summary>/// 将 Image(PNG) 保存到指定目录文件名的 Icon/// </summary>/// <param name="image"></param>/// <param name="file"></param>/// <returns></returns>public static bool Save(Image image, string file){    if (image != null)    {        using (Icon icon = ConvertToIcon(image))        {            try            {                FileStream fs = new FileStream(file, FileMode.Create, FileAccess.Write);                icon.Save(fs);                fs.Flush();                fs.Close();                fs.Dispose();                return true;            }            catch { }        }    }    return false;}/// <summary>/// 转换Image为Icon/// </summary>/// <param name="image">要转换为图标的Image对象</param>/// <param name="nullTonull">当image为null时是否返回null。false则抛空引用异常</param>/// <exception cref="ArgumentNullException" />public static Icon ConvertToIcon(Image image, bool nullTonull = false){    if (image == null)    {        if (nullTonull) { return null; }        throw new ArgumentNullException("image");    }    using (MemoryStream msImg = new MemoryStream()                        , msIco = new MemoryStream())    {        image.Save(msImg, ImageFormat.Png);        using (var bin = new BinaryWriter(msIco))        {            //写图标头部            bin.Write((short)0);           //0-1保留            bin.Write((short)1);           //2-3文件类型。1=图标, 2=光标            bin.Write((short)1);           //4-5图像数量(图标可以包含多个图像)            bin.Write((byte)image.Width);  //6图标宽度            bin.Write((byte)image.Height); //7图标高度            bin.Write((byte)0);            //8颜色数(若像素位深>=8,填0。这是显然的,达到8bpp的颜色数最少是256,byte不够表示)            bin.Write((byte)0);            //9保留。必须为0            bin.Write((short)0);           //10-11调色板            bin.Write((short)32);          //12-13位深            bin.Write((int)msImg.Length);  //14-17位图数据大小            bin.Write(22);                 //18-21位图数据起始字节            //写图像数据            bin.Write(msImg.ToArray());            bin.Flush();            bin.Seek(0, SeekOrigin.Begin);            return new Icon(msIco);        }    }}

这个方法所转换的 Icon 是无损带透明的完美效果。

注:这里补充个小代码,是 OpenFileDialog 选择文件的:

OpenFileDialog 中可以设置 Filter 属性,默认不设置则可以选择所有文件,也可以限制只选自己需要的文件类型。
1. 限制一种文件类型:Filter=”照片|*.jpg”;
2. 限制同类多种文件类型:Filter=”照片|*.jpg;*jpeg;*png”;
3. 限制多种分类文件类型:Filter=”照片|.jpg;*jpeg;*png|音频|.mp3”;

代码如下:

//弹出打开图片对话框OpenFileDialog fileDialog = new OpenFileDialog();fileDialog.Filter = "图片文件|*.jpg;*.jpeg;*.png";if (fileDialog.ShowDialog() == DialogResult.OK){    //选择图片进行加载    oriImagePath = fileDialog.FileName;}

2、可放大的程序图标

用过 win7 的小伙伴大部分应该都知道的,按住 ctrl 键 + 鼠标滚轮 可以对程序图标放大缩小,但是固定尺寸的程序图标就不会跟着放大缩小,如图:

这种问题其实倒还是简单,因为 Icon 文件中可以放不同分辨率的图像,只需要在文件中创建高分辨率的版本就可以了:

创建多个分辨率的 Icon 之后,就不怕缩放问题了:

3、音量合成器的 Icon

沉积在可以放大图标的喜悦中之后,在给程序加声音的工作中,突然发现了个奇葩的东西:

我去~这是个什么鬼,在网上没查到是什么原因,我真是不知道怎么来描述这个问题……不过可以肯定是出在大分辨率的 Icon 上,既然这样,就再增加小分辨率的 Icon 进去。

实验发现,增加48*48大小的 Icon 就可以恢复正常了,如图:

4、IcoFX

IcoFX 确实是款不错的 Ico 文件编辑工具,上面的例子我也是用了这个软件编辑的 Ico,相比 visual studio 中的图像编辑器,IcoFX 操作更方便些,感兴趣的同学可以下载学习一下,软件有试用期,但是毕竟有注册机之类的神器啊,百度一下就可以了。

(0)

相关推荐