by Dejan Jelovic
Visual Studio .NET seems to have a weird model for adding and managing resources such as bitmaps and locale-specific strings. It doesn't work in all the cases, it's illogical, tool support is poor, and it's badly documented.
This document is a tutorial that makes sense of this mess.
Here's how things break down:
In Visual Studio .NET, many resources are no longer specified using .RC files. Instead, the form editor directly manipulates your VB or C# code when you edit the forms visually..
We still need other types of resources, though. We need graphic resources like bitmaps and icons, as well as locale-specific string resources. These are typically stored in one or more .RESX files that make up a Visual Studio project.
In order to use resources from your code, you'll need to know how to:
So let's get started.
Visual Studio .NET stores resources like bitmaps, icons and locale-specific strings in files with the extension .RESX. These are actually XML files in which binary resources are base64-encoded.
When you compile a project the compiler will compile these files into binary files with the .resource extension, and then the linker will put these into the final EXE or DLL.
Adding a new RESX file to a project is simple. Simply right-click on a project in the Solution Explorer, select Add/Add New Resource, and add a new "Assembly Resource File".
Here's the funny thing: Visual Studio doesn't seem to have any tools for visually editing resources in a RESX file.
Fortunately, a Lutz Roeder has created a tool named Resourcer that you can use to edit them.
To add a bitmap to a RESX file:
And you are done. BTW, you don't need to keep the bitmap file on the disk any more, as the RESX file contains its complete copy.
Here's how to load the bitmap from the resources at run time:
The first thing you should know is under which name Visual Studio has placed your RESX file into the resulting EXE.
Each Visual Studio project has a namespace name associated with it. If you right-click on a project file in Solution Explorer, then select Properties, a dialog that pops up lets you select a "Default Namespace". Visual Studio will bundle the resources into the resulting EXE under the name made up from the default namespace and the name of the RESX file.
Say your default namespace is MyCompany.MyProject and the RESX file is named SomeResources. Those resources will be bundled inside the resulting executable under the name MyCompany.MyProject.SomeResources.
To access those resources from your code, you'll need to create an instance of ResourceManager:
ResourceManager resourceManager = new ResourceManager ("MyCompany.MyProject.SomeResources", GetType ().Assembly);
Then, to obtain bitmap, you will use the symbolic name that you have specified when you have added the bitmap to the RESX file using Resourcer:
Bitmap image = (Bitmap)resourceManager.GetObject ("MyBitmapName");
If you attempt to create a resource manager using a wrong name, or you specify a wrong name when calling ResourceManager.GetObject, the framework will throw the MissingManifestResourceException.
That's it. Have fun now.
I just got an e-mail from Ian Griffiths. He tells me that there's an easier way to store locale-neutral resources (typically icons and bitmaps) in a project. Simply add them to the project as you would any other file, and then set their Build Action to Embedded Resource.
Loading these is still weird, though. Say you want to load a bitmap. The easiest way to do that is to use the class Bitmap constructor of the form:
Bitmap (Type type, string resource);
The first parameter is the type that "owns" the resource, and the second is the name of the resource.
Now comes the weird part: The resource loader attempts to load the resource which has the name of the namespace to which type belongs, plus the passed resource name. So if you are inside a method of a class MyCompany.MyProject.MySubProject.MyClass and you attempt to load a resource named MyBitmap.bmp by executing:
Bitmap bitmap = new Bitmap (GetType (), "MyBitmap.bmp");
Then the resource loader will attempt to load the resource named MyCompany.MyProject.MySubProject.MyBitmap.bmp.
How do you get a resource to have that name? Simply, the resource name in the manifest is formed from the project's default namespace and it's filename. So if your project's default namespace is MyCompany.MyProject, you'll need to name the bitmap file MySubProject.MyBitmap.bmp.
[footer.htm]