在进行项目开发时,经常需要在不同的项目中重用图像和图标,或者需要调整图像尺寸以适应不同的需求。然而,寻找和重用这些资源可能会非常耗时,因为需要在多个磁盘或网络上搜索。此外,如果想使用一个没有参与开发的程序集中的图像或图标,也会面临同样的挑战。
为了解决这些问题,可以利用资源解析器(Resource Resolver)来列出和提取图标、图像和字符串资源。所有资源项类都派生自IResourceItem接口。
资源项接口定义:
#region Properties
string Name {
get;
set;
}
object Value {
get;
set;
}
ResourceType ResourceType {
get;
}
int BoundHeight {
get;
}
#endregion
#region Methods
void Save();
void Draw(Graphics graphics, Font font, Rectangle bound);
#endregion
其中,Draw方法用于在列表中列出项,而Save方法用于从列表中保存为默认项。
资源解析:
要解析资源,首先使用反射来获取程序集信息和选定文件的清单资源名称。解析完程序集清单名称后,逐个解析所有清单文件。
Assembly assembly = Assembly.LoadFile(fileName);
string[] names = assembly.GetManifestResourceNames();
for (int i = 0; i < names.Length; i++) {
ManifestResourceInfo info = assembly.GetManifestResourceInfo(names[i]);
ResourceContainer container = new ResourceContainer(names[i]);
container.Resolve(assembly, names[i]);
cbResources.Items.Add(container);
}
在解析资源时,会创建一个资源项列表。如果资源流不为空,会检查资源位置是否为嵌入的,并且名称是否以".resources"结尾。如果是,会使用ResourceReader来读取资源数据,并根据资源类型创建相应的资源项。
public void Resolve(Assembly assembly, string name) {
_Items = new List();
Stream resourceStream = assembly.GetManifestResourceStream(name);
if (resourceStream == null) return;
ManifestResourceInfo info = assembly.GetManifestResourceInfo(name);
if ((info.ResourceLocation & ResourceLocation.Embedded) == ResourceLocation.Embedded && name.EndsWith(".resources")) {
ResourceReader reader = new ResourceReader(resourceStream);
IDictionaryEnumerator enumerator = reader.GetEnumerator();
while (enumerator.MoveNext()) {
string type = string.Empty;
string key = enumerator.Key.ToString();
byte[] values = null;
reader.GetResourceData(key, out type, out values);
List items = ResourceItem.GetResourceItem(key, enumerator.Value, resourceStream);
if (items != null) {
for (int i = 0; i < items.Count; i++) {
Items.Add(items[i]);
}
}
}
}
}
创建资源项:
根据资源类型创建资源项。例如,如果资源类型是字符串,会创建一个StringResourceItem;如果是图标,会创建一个IconResourceItem;如果是图像列表,会创建多个ImageResourceItem。
public static List GetResourceItem(string name, object value, Stream stream) {
if (value is string) {
StringResourceItem item = new StringResourceItem(name, value);
return new List() { item };
} else if (value is Icon) {
IconResourceItem item = new IconResourceItem(name, value);
return new List() { item };
} else if (value is ImageListStreamer) {
List items = new List();
using (ImageList list = new ImageList()) {
list.ImageStream = value as ImageListStreamer;
int index = 0;
foreach (Image image in list.Images) {
items.Add(new ImageResourceItem(name, image, index));
index++;
}
}
return items;
} else if (value is Image) {
ImageResourceItem item = new ImageResourceItem(name, value, -1);
return new List() { item };
} else {
object v = value;
}
return null;
}
保存图像:
private void _SaveAllImages() {
if (cbResources.Items.Count == 0) {
_LoadResources();
}
lblMessage.Text = "Saving...";
Application.DoEvents();
using (FolderBrowserDialog dialog = new FolderBrowserDialog()) {
if (!string.IsNullOrEmpty(Properties.Settings.Default.DefaultSavePath)) {
dialog.SelectedPath = Properties.Settings.Default.DefaultSavePath;
}
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
Properties.Settings.Default.DefaultSavePath = dialog.SelectedPath;
Properties.Settings.Default.Save();
string iconDirectory = dialog.SelectedPath + "\\Icons";
string imageDirectory = dialog.SelectedPath + "\\Images";
if (!Directory.Exists(iconDirectory)) Directory.CreateDirectory(iconDirectory);
if (!Directory.Exists(imageDirectory)) Directory.CreateDirectory(imageDirectory);
for (int resourceIndex = 0; resourceIndex < cbResources.Items.Count; resourceIndex++) {
ResourceContainer container = cbResources.Items[resourceIndex] as ResourceContainer;
string[] names = container.Name.Split(new char[] { '.' });
for (int itemIndex = 0; itemIndex < container.Items.Count; itemIndex++) {
IResourceItem item = container.Items[itemIndex];
string fileName = string.Empty;
if (item.ResourceType == ResourceType.Icon) {
IconResourceItem resourceItem = item as IconResourceItem;
if (resourceItem.Icon != null) {
if (names.Length > 1) {
fileName = dialog.SelectedPath + "\\Icons\\" + names[names.Length - 2] + ".ico";
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) {
resourceItem.Icon.Save(fs);
fs.Flush();
}
}
}
} else if (item.ResourceType == ResourceType.Image) {
ImageResourceItem imageItem = item as ImageResourceItem;
if (imageItem.Image != null) {
string name = imageItem.Name;
if (imageItem.Index != -1) {
name = imageItem.Index.ToString();
}
fileName = dialog.SelectedPath + "\\Images\\" + names[names.Length - 2] + "_" + imageItem.Width.ToString() + "_" + name + ".png";
imageItem.Image.Save(fileName, ImageFormat.Png);
}
}
}
}
MessageBox.Show("Operation Finished", "Success", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
}
}
lblMessage.Visible = false;
}