WinForms .NET 2.0:如何绘制适当大小的图标? [英] WinForms .NET 2.0: How to paint the proper sized icon?

查看:103
本文介绍了WinForms .NET 2.0:如何绘制适当大小的图标?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含48x48和256x256 Vista PNG版本(以及32x32和16x16版本)的ico文件。我想使用合适的内部尺寸版本来绘制图标。



我试过了:

  Icon ico = Properties.Resources.TestIcon; 
e.Graphics.DrawIcon(ico,new Rectangle(0,0,48,48));
e.Graphics.DrawIcon(ico,new Rectangle(48,0,256,256));

但他们将32x32版本分别渲染为48x48和256x256。



我试过:

  Icon ico = Properties.Resources .TestIcon; 
e.Graphics.DrawIconUnstretched(ico,new Rectangle(0,0,48,48));
e.Graphics.DrawIconUnstretched(ico,new Rectangle(48 0,256,256));

但是这些绘制32x32版本unrightched。



我试过了:

  Icon ico = Properties.Resources.TestIcon; 
e.Graphics.DrawImage(ico.ToBitmap(),new Rectangle(0,0,48,48));
e.Graphics.DrawImage(ico.ToBitmap(),new Rectangle(48,0,256,256));

但是这些绘制了32x32图标的延伸版本。



我如何使用适当的尺寸绘制图标本身?



另外,我想绘制使用16x16版本。我试过:

  Icon ico = Properties.Resources.TestIcon; 
e.Graphics.DrawIcon(ico,new Rectangle(0,0,16,16));
e.Graphics.DrawIconUnstretched(ico,new Rectangle(24,0,16,16));
e.Graphics.DrawImage(ico.ToBitmap(),new Rectangle(48,0,16,16));

但是所有这些都使用32x32版本缩小,除了 Unstretched call,将它裁剪为16x16。



我如何使用适当的尺寸绘制图标?






遵循schnaader的建议,用你需要的大小构建一个图标副本不适用于256x256的大小。即以下不起作用(它使用48x48图标的缩放版本):

  e.Graphics.DrawIcon(
new Icon(ico,new Size(256,256)),
new Rectangle(0,0,256,256));

虽然以下两个方法可行:

  e.Graphics.DrawIcon(
new Icon(ico,new Size(16,16)),
new Rectangle(0,0,16,16)) ;

e.Graphics.DrawIcon(
new Icon(ico,new Size(48,48)),
new Rectangle(0,0,48,48));


解决方案

今天,我为从Vista图标中提取256x256位图



我用它在About框中显示大图标( 256x256 )作为位图。例如,此代码将Vista图标作为PNG图像获取,并将其显示在256x256 PictureBox中:

  picboxAppLogo.Image = ExtractVistaIcon Icon.ExtractAssociatedIcon(myIcon)); 

这个函数将Icon对象作为参数。因此,您可以将它用于任何图标 - 来自资源,来自文件,来自流等。 (请阅读下面关于提取EXE图标的信息)。



它运行在任何操作系统上,因为它不是使用任何操作系统Win32 API,它是 100%托管代码: - )

  //基于:http: //www.codeproject.com/KB/cs/IconExtractor.aspx 
//以及提示:http://www.codeproject.com/KB/cs/IconLib.aspx

位图ExtractVistaIcon(Icon icoIcon)
{
位图bmpPngExtracted = null;
尝试
{
byte [] srcBuf = null;
using(System.IO.MemoryStream stream = new System.IO.MemoryStream())
{icoIcon.Save(stream); srcBuf = stream.ToArray(); }
const int SizeICONDIR = 6;
const int SizeICONDIRENTRY = 16;
int iCount = BitConverter.ToInt16(srcBuf,4);
for(int iIndex = 0; iIndex< iCount; iIndex ++)
{
int iWidth = srcBuf [SizeICONDIR + SizeICONDIRENTRY * iIndex];
int iHeight = srcBuf [SizeICONDIR + SizeICONDIRENTRY * iIndex + 1];
int iBitCount = BitConverter.ToInt16(srcBuf,SizeICONDIR + SizeICONDIRENTRY * iIndex + 6);
if(iWidth == 0&& iHeight == 0&& iBitCount == 32)
{
int iImageSize = BitConverter.ToInt32(srcBuf,SizeICONDIR + SizeICONDIRENTRY * iIndex + 8);
int iImageOffset = BitConverter.ToInt32(srcBuf,SizeICONDIR + SizeICONDIRENTRY * iIndex + 12);
System.IO.MemoryStream destStream = new System.IO.MemoryStream();
System.IO.BinaryWriter writer = new System.IO.BinaryWriter(destStream);
writer.Write(srcBuf,iImageOffset,iImageSize);
destStream.Seek(0,System.IO.SeekOrigin.Begin);
bmpPngExtracted =新的位图(destStream); //这是PNG! :)
休息;
}
}
}
catch {return null; }
return bmpPngExtracted;

重要!如果您想加载此图标直接从EXE文件中,然后你 CAN NOT 使用 Icon.ExtractAssociatedIcon(Application.ExecutablePath)作为参数,因为.NET函数ExtractAssociatedIcon()非常愚蠢,它会提取ONLY 32x32图标!



相反,您最好使用由Tsuda Kageyu创建的 IconExtractor 类( http://www.codeproject.com/KB/cs/IconExtractor.aspx )。你可以稍微简化一下这个课程,使它更小。使用 IconExtractor 这种方式:

  //从EXE获取FILL图标集,并提取256x256版本logo ... 
using(TKageyu.Utils.IconExtractor IconEx = new TKageyu.Utils.IconExtractor(Application.ExecutablePath))
{
Icon icoAppIcon = IconEx.GetIcon(0); //因为标准System.Drawing.Icon.ExtractAssociatedIcon()只返回32x32。
picboxAppLogo.Image = ExtractVistaIcon(icoAppIcon);
}

注意:我仍然在使用我的ExtractVistaIcon()函数,因为我不喜欢 IconExtractor 如何处理此作业 - 首先,它使用IconExtractor.SplitIcon(icoAppIcon)提取所有图标格式,然后您必须知道确切的256x256图标索引才能获得所需的vista-图标。所以,在这里使用我的ExtractVistaIcon()更快更简单:)

i have an ico file that contains a 48x48 and a 256x256 Vista PNG version (as well as the 32x32 and 16x16 versions). i want to draw the icon using the appropriate internal size version.

i've tried:

Icon ico = Properties.Resources.TestIcon;
e.Graphics.DrawIcon(ico, new Rectangle(0, 0, 48, 48));
e.Graphics.DrawIcon(ico, new Rectangle(48, 0, 256, 256));

But they draw the 32x32 version blown up to 48x48 and 256x256 respectively.

i've tried:

Icon ico = Properties.Resources.TestIcon;
e.Graphics.DrawIconUnstretched(ico, new Rectangle(0, 0, 48, 48));
e.Graphics.DrawIconUnstretched(ico, new Rectangle(48 0, 256, 256));

But those draw the 32x32 version unstretched.

i've tried:

Icon ico = Properties.Resources.TestIcon;
e.Graphics.DrawImage(ico.ToBitmap(), new Rectangle(0, 0, 48, 48));
e.Graphics.DrawImage(ico.ToBitmap(), new Rectangle(48, 0, 256, 256));

But those draw a stretched version of the 32x32 icon.

How do i make the icon draw itself using the appropriate size?

Additionally, i want to draw using the 16x16 version. i've tried:

Icon ico = Properties.Resources.TestIcon;
e.Graphics.DrawIcon(ico, new Rectangle(0, 0, 16, 16));
e.Graphics.DrawIconUnstretched(ico, new Rectangle(24, 0, 16, 16));
e.Graphics.DrawImage(ico.ToBitmap(), new Rectangle(48, 0, 16, 16));

But all those use the 32x32 version scaled down, except for the Unstretched call, which crops it to 16x16.

How do i make the icon draw itself using the appropriate size?


Following schnaader's suggestion of constructing a copy of the icon with the size you need doesn't work for 256x256 size. i.e. the following does not work (it uses a scaled version of the 48x48 icon):

e.Graphics.DrawIcon(
        new Icon(ico, new Size(256, 256)), 
        new Rectangle(0, 0, 256, 256));

While the following two do work:

e.Graphics.DrawIcon(
        new Icon(ico, new Size(16, 16)), 
        new Rectangle(0, 0, 16, 16));

e.Graphics.DrawIcon(
        new Icon(ico, new Size(48, 48)), 
        new Rectangle(0, 0, 48, 48));

解决方案

Today, I made a very nice function for extracting the 256x256 Bitmaps from Vista icons.

I use it to display the large icon ( 256x256 ) as a Bitmap in "About" box. For example, this code gets Vista icon as PNG image, and displays it in a 256x256 PictureBox:

picboxAppLogo.Image = ExtractVistaIcon(Icon.ExtractAssociatedIcon(myIcon));

This function takes Icon object as a parameter. So, you can use it with any icons - from resources, from files, from streams, and so on. (Read below about extracting EXE icon).

It runs on any OS, because it does not use any Win32 API, it is 100% managed code :-)

// Based on: http://www.codeproject.com/KB/cs/IconExtractor.aspx
// And a hint from: http://www.codeproject.com/KB/cs/IconLib.aspx

Bitmap ExtractVistaIcon(Icon icoIcon)
{
    Bitmap bmpPngExtracted = null;
    try
    {
        byte[] srcBuf = null;
        using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
            { icoIcon.Save(stream); srcBuf = stream.ToArray(); }
        const int SizeICONDIR = 6;
        const int SizeICONDIRENTRY = 16;
        int iCount = BitConverter.ToInt16(srcBuf, 4);
        for (int iIndex=0; iIndex<iCount; iIndex++)
        {
            int iWidth  = srcBuf[SizeICONDIR + SizeICONDIRENTRY * iIndex];
            int iHeight = srcBuf[SizeICONDIR + SizeICONDIRENTRY * iIndex + 1];
            int iBitCount   = BitConverter.ToInt16(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 6);
            if (iWidth == 0 && iHeight == 0 && iBitCount == 32)
            {
                int iImageSize   = BitConverter.ToInt32(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 8);
                int iImageOffset = BitConverter.ToInt32(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 12);
                System.IO.MemoryStream destStream = new System.IO.MemoryStream();
                System.IO.BinaryWriter writer = new System.IO.BinaryWriter(destStream);
                writer.Write(srcBuf, iImageOffset, iImageSize);
                destStream.Seek(0, System.IO.SeekOrigin.Begin);
                bmpPngExtracted = new Bitmap(destStream); // This is PNG! :)
                break;
            }
        }
    }
    catch { return null; }
    return bmpPngExtracted;
}

IMPORTANT! If you want to load this icon directly from EXE file, then you CAN'T use Icon.ExtractAssociatedIcon(Application.ExecutablePath) as a parameter, because .NET function ExtractAssociatedIcon() is so stupid, it extracts ONLY 32x32 icon!

Instead, you better use the whole IconExtractor class, created by Tsuda Kageyu (http://www.codeproject.com/KB/cs/IconExtractor.aspx). You can slightly simplify this class, to make it smaller. Use IconExtractor this way:

// Getting FILL icon set from EXE, and extracting 256x256 version for logo...
using (TKageyu.Utils.IconExtractor IconEx = new TKageyu.Utils.IconExtractor(Application.ExecutablePath))
{
    Icon icoAppIcon = IconEx.GetIcon(0); // Because standard System.Drawing.Icon.ExtractAssociatedIcon() returns ONLY 32x32.
    picboxAppLogo.Image = ExtractVistaIcon(icoAppIcon);
}

Note: I'm still using my ExtractVistaIcon() function here, because I don't like how IconExtractor handles this job - first, it extracts all icon formats by using IconExtractor.SplitIcon(icoAppIcon), and then you have to know the exact 256x256 icon index to get the desired vista-icon. So, using my ExtractVistaIcon() here is much faster and simplier way :)

这篇关于WinForms .NET 2.0:如何绘制适当大小的图标?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆