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

eom*_*off 2 c# icons

我想用SystemIcons.Warning它,但它太大了我的需要.我想调整它的大小.

我试过了 :

Icon sizedIcon = new Icon(SystemIcons.Warning, new Size(10,10));
Run Code Online (Sandbox Code Playgroud)

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

有什么建议?

Han*_*ant 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);
}
Run Code Online (Sandbox Code Playgroud)

样品用法:

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

它确实看起来比SystemIcons.Warning更好.当你使用16x16时,它是干净的.