1

I have a controls library which I've added a .resx file to (ImageResources.resx). It contains two .png images which I subsequently added.

In that same library I have a control which loads a couple of images to do some custom drawing, but I don't seem to be able to load the resources:

void GTableLayoutPanel::SetBorderImagesFromManifest(String^ topLeftCornerImageName, String^ topImageName) { // Grab the assembly this is being called from Assembly^ assembly = Assembly::GetExecutingAssembly(); // Grab the images from the assembly Stream^ stream = assembly->GetManifestResourceStream(topLeftCornerImageName); Image^ topLeftImage = System::Drawing::Image::FromStream(stream); stream = assembly->GetManifestResourceStream(topImageName); Image^ topImage = System::Drawing::Image::FromStream(stream); // Update the internal store from the supplied images SetBorderImages(topLeftImage, topImage); } 

...gives me errors complaining that stream is null which suggests my call to GetManifestResourceStream is failing.

The images are called group_box_top.png and group_box_top_left.png and I'm calling the image loader as follows:

SetBorderImagesFromManifest("group_box_top_left.png", "group_box_top.png"); 

I've also tried:

SetBorderImagesFromManifest("group_box_top_left", "group_box_top"); 

...because the files appear in the .resx file without the .png extensions, but this gives the same error.

Have I missed a step here?

[Edit] I tried the suggestion in that final link and I get:

MyControlsLib.ImageResources.resources 

So now I've tried referencing:

Stream^ strm1 = assembly->GetManifestResourceStream("MyControlsLib.ImageResources.resources.group_box_top_left"); Stream^ strm2 = assembly->GetManifestResourceStream("MyControlsLib.ImageResources.resources.group_box_top_left.png"); Stream^ strm3 = assembly->GetManifestResourceStream("MyControlsLib.ImageResources.group_box_top_left"); Stream^ strm4 = assembly->GetManifestResourceStream("MyControlsLib.ImageResources.group_box_top_left.png"); 

...all of which return nullptr :-/

3
  • Don't try my exact suggestion - I'm not sure you require the ImageResources part and might still need to include the extension. Use the code in the question about getting the names to get the real names and subsitute those in the code. Also, I'd comment on people's answers as I don't get any notifications about your question. Commented Jul 19, 2010 at 16:07
  • See the comment on your answer.. Commented Jul 19, 2010 at 16:15
  • Ah right, not sure then - the problem is likely the qualified name, but I'm not sure how this applies to C++.NET Commented Jul 19, 2010 at 17:53

3 Answers 3

5

I finally got the magic combination for a C++/CLI solution. So just in case anyone else has this issue:

Method 1 (via .resx file)

  1. Add the image files (I used .pngs, but bitmaps etc. work too).
  2. Add a resource file:
    1. Go to Solution Explorer.
    2. Right-click on Resource Files in the project you're adding to
    3. Select Add > New Item..
    4. Choose Visual C++ > Resource > Assembly Resource File (.resx). I nameed mine "ImageResources.resx"
  3. Add the images:
    1. Double click on "ImageResources.resx" in Solution Explorer
    2. Click on the Add Resource button and select Add Existing File...
    3. Select the images you want to embed. I added group_box_top.png and group_box_top_left.png which appear in the .resx file as group_box_top and group_box_top_left.

You can then grab the images from the manifest with:

// Grab the assembly this is being called from Assembly^ assembly = Assembly::GetExecutingAssembly(); AssemblyName^ assemblyName = assembly->GetName(); // Grab the images from the assembly ResourceManager^ rm = gcnew ResourceManager(assemblyName->Name+".ImageResources", assembly); Bitmap^ topLeftImage = (Bitmap^)rm->GetObject("group_box_top_left"); Bitmap^ topImage = (Bitmap^)rm->GetObject("group_box_top"); 

Note that the ImageResources string passed into the ResourceManager constructor must match the name of your .resx file.

Method 2 (via linker)

  1. Add the files:
    1. Right-click on your project
    2. Go to Linker -> Input
    3. Add the files you want to embed to the Embed Managed Resource File property. I added PingSend.wav here.

To get access to the files simply do:

System::Reflection::Assembly^ assembly = Assembly::GetExecutingAssembly(); System::Media::Sonudplayer^ pingPlayer = gcnew System::Media::SoundPlayer(assembly->GetManifestResourceStream("PingSend.wav")); 

..which in this case, loads the audio file ready to play back.

Sign up to request clarification or add additional context in comments.

Comments

1

I think the path to the resource item might need to be fully qualified:

GetManifestResourceStream("MyNamespace.ImageResources.group_box_top_left") 

This link shows a C# example (sorry), notice when creating the stream it has the namespace in the arguments:

http://support.microsoft.com/kb/319292

This also goes onto how to find the fully qualified path to a resource:

How can I discover the "path" of an embedded resource?

2 Comments

I did use the code in the question you linked and it gave me MyControlsLib.ImageResources.resources as per my edit..
+1: Thanks for the suggestions. None of them quite worked, but it at least put me on the right path.
0
System::Reflection::Assembly^ assembly = System::Reflection::Assembly::GetExecutingAssembly(); Resources::ResourceManager^ rm = gcnew Resources::ResourceManager("namespaceName" + ".ResourceFileName", assembly); this->button->Image = cli::safe_cast<Image^>(rm->GetObject("image1")); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.