开发者

Why can't I load an image resource from my resx file?

开发者 https://www.devze.com 2023-01-08 10:34 出处:网络
I have a controls library which I\'ve added a .resx file to (ImageResources.resx). It contains two .png images which I subsequently added.

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
    St开发者_运维百科ream^ 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 :-/


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.


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?


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"));
0

精彩评论

暂无评论...
验证码 换一张
取 消