在C#中调整系统图标大小

时间:2014-07-11 10:50:45

标签: c# icons

我想使用SystemIcons.Warning,但这对我的需求来说太大了。我想调整它的大小。

我试过了:

Icon sizedIcon = new Icon(SystemIcons.Warning, new Size(10,10));

但它不起作用,图标保持不变。

有什么建议吗?

1 个答案:

答案 0 :(得分:8)

.NET Icon类非常瘫痪,由于曾经相关的Windows 98和Windows 2000支持,它在过去的十年中停滞不前。除此之外,Windows不支持加载任何大小的系统图标其他而不是系统的默认图标大小。通常为32x32。调整它的大小将不可避免地看起来很糟糕。

请记住,没有任何图标可以在10x10上看起来很好。它只是现代显示器上的一个斑点。你可以从一个接近所需最终尺寸的图标大小开始,稍微提前一点,所需调整大小越小,它看起来仍然合理的几率就越大。如果可以,请选择可能出现在图标中的尺寸。像16x16,32x32,48x48。

Anyhoo,这个可修复的。请记住,这需要相当多的hack-o-rama,因为Windows并不直接支持这一点。所需要的是直接从系统DLL资源中读取图标。使用更现代的winapi,LoadImage()而不是.NET使用的那个,LoadIcon()。适用于XP及以上版本。

在项目中添加一个新类并粘贴此代码:

using System;
using System.Drawing;
using System.Reflection;
using System.Runtime.InteropServices;

public class IconEx : IDisposable {
    public enum SystemIcons {
        Application = 100,
        Asterisk = 104,
        Error = 103,
        Exclamation = 101,
        Hand = 103,
        Information = 104,
        Question = 102,
        Shield = 106,
        Warning = 101,
        WinLogo = 100
    }

    public IconEx(string path, Size size) {
        IntPtr hIcon = LoadImage(IntPtr.Zero, path, IMAGE_ICON, size.Width, size.Height, LR_LOADFROMFILE);
        if (hIcon == IntPtr.Zero) throw new System.ComponentModel.Win32Exception();
        attach(hIcon);

    }
    public IconEx(SystemIcons sysicon, Size size) {
        IntPtr hUser = GetModuleHandle("user32");
        IntPtr hIcon = LoadImage(hUser, (IntPtr)sysicon, IMAGE_ICON, size.Width, size.Height, 0);
        if (hIcon == IntPtr.Zero) throw new System.ComponentModel.Win32Exception();
        attach(hIcon);
    }


    public Icon Icon {
        get { return this.icon; }
    }

    public void Dispose() {
        if (icon != null) icon.Dispose();
    }

    private Icon icon;

    private void attach(IntPtr hIcon) {
        // Invoke the private constructor so we can get the Icon object to own the handle
        var ci = typeof(Icon).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, 
            null, new Type[] { typeof(IntPtr), typeof(bool) }, null);
        this.icon = (Icon)ci.Invoke(new object[] { hIcon, true});
    }

    private const int IMAGE_ICON = 1;
    private const int LR_LOADFROMFILE = 0x10;
    private const int LR_SHARED = 0x8000;

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr GetModuleHandle(string name);
    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr LoadImage(IntPtr hinst, string lpszName, int uType,
                                 int cxDesired, int cyDesired, int fuLoad);
    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    private static extern IntPtr LoadImage(IntPtr hinst, IntPtr resId, int uType,
                                 int cxDesired, int cyDesired, int fuLoad);
}

样本用法:

    using (var icon = new IconEx(IconEx.SystemIcons.Warning, new Size(10, 10))) {
        e.Graphics.DrawIcon(icon.Icon, 0, 0);
    }

看起来比SystemIcons.Warning更好。当您使用16x16时,它会发出干净的声音。