为什么我无法从resx文件加载图像资源?

时间:2010-07-19 15:27:46

标签: .net resources c++-cli manifest resx

我有一个控件库,我已经将.resx文件添加到(ImageResources.resx)。它包含两个.png图像,我随后添加了它。

在同一个库中我有一个控件可以加载几个图像来做一些自定义绘图,但我似乎无法加载资源:

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);
}

...给我错误抱怨stream为空,这表示我对GetManifestResourceStream的调用失败。

图像被称为group_box_top.pnggroup_box_top_left.png,我按如下方式调用图像加载器:

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

我也试过了:

SetBorderImagesFromManifest("group_box_top_left", "group_box_top");

...因为文件出现在没有.png扩展名的.resx文件中,但这会产生同样的错误。

我错过了一步吗?

[编辑] 我在最后一个链接中尝试了这个建议,我得到了:

MyControlsLib.ImageResources.resources

所以现在我尝试引用:

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

...所有这些都返回nullptr: - /

3 个答案:

答案 0 :(得分:3)

我终于获得了C ++ / CLI解决方案的神奇组合。所以,万一其他人有这个问题:

方法1(通过.resx文件)

  1. 添加图像文件(我使用.pngs,但位图等也可以使用)。
  2. 添加资源文件:
    1. 转到解决方案资源管理器。
    2. 右键点击要添加到
    3. 的项目中的Resource Files
    4. 选择Add> New Item..
    5. 选择Visual C++> Resource> Assembly Resource File (.resx)。我将我的名字命名为“ImageResources.resx”
  3. 添加图片:
    1. 双击解决方案资源管理器中的“ImageResources.resx”
    2. 点击Add Resource按钮,然后选择Add Existing File...
    3. 选择要嵌入的图像。我添加了group_box_top.pnggroup_box_top_left.png作为group_box_topgroup_box_top_left出现在.resx文件中。
  4. 然后,您可以使用以下方式从清单中抓取图像:

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

    请注意,传递到ImageResources构造函数的ResourceManager字符串必须与.resx文件的名称匹配。

    方法2(通过链接器)

    1. 添加文件:
      1. 右键单击您的项目
      2. 转到Linker - > Input
      3. 将要嵌入的文件添加到Embed Managed Resource File属性中。我在这里添加了PingSend.wav
    2. 要访问文件,只需执行以下操作:

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

      ..在这种情况下,加载准备播放的音频文件。

答案 1 :(得分:1)

我认为资源项的路径可能需要完全限定:

GetManifestResourceStream("MyNamespace.ImageResources.group_box_top_left")

此链接显示了一个C#示例(抱歉),注意创建流时它在参数中具有命名空间:

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

这也涉及如何找到资源的完全限定路径:

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

答案 2 :(得分: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"));