我想使用SystemIcons.Warning
,但这对我的需求来说太大了。我想调整它的大小。
我试过了:
Icon sizedIcon = new Icon(SystemIcons.Warning, new Size(10,10));
但它不起作用,图标保持不变。
有什么建议吗?
答案 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时,它会发出干净的声音。