Почему я не могу загрузить ресурс изображения из моего файла 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 имеет значение null, что говорит о том, что мой вызов GetManifestResourceStream не работает.

Изображения называются group_box_top.png и group_box_top_left.png, и я вызываю загрузчик изображений следующим образом:

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

Я также пробовал:

SetBorderImagesFromManifest("group_box_top_left", "group_box_top");

... потому что файлы появляются в файле .resx без расширений .png, но это дает ту же ошибку.

Я что-то здесь пропустил?

[Edit] Я попробовал предложение из последней ссылки и получил:

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: - /


person Jon Cage    schedule 19.07.2010    source источник
comment
Не пробуйте мое точное предложение - я не уверен, что вам нужна часть ImageResources, и, возможно, все же потребуется включить расширение. Используйте код в вопросе о получении имен, чтобы получить настоящие имена и заменить их в коде. Кроме того, я бы прокомментировал ответы людей, так как я не получаю уведомлений о вашем вопросе.   -  person Adam Houldsworth    schedule 19.07.2010
comment
См. Комментарий к вашему ответу ..   -  person Jon Cage    schedule 19.07.2010
comment
Ага, тогда не уверен - проблема, скорее всего, в квалифицированном имени, но я не уверен, как это применимо к C ++. NET   -  person Adam Houldsworth    schedule 19.07.2010


Ответы (2)


Наконец-то я получил волшебную комбинацию для решения C ++ / CLI. Так что на всякий случай, если у кого-то еще есть эта проблема:

Метод 1 (через RESX-файл)

  1. Добавьте файлы изображений (я использовал .pngs, но растровые изображения и т. Д. Тоже работают).
  2. Add a resource file:
    1. Go to Solution Explorer.
    2. Щелкните правой кнопкой мыши Resource Files в проекте, который вы добавляете.
    3. Выберите Add> New Item..
    4. Выберите Visual C++> Resource> Assembly Resource File (.resx). Я назвал свой "ImageResources.resx"
  3. Add the images:
    1. Double click on "ImageResources.resx" in Solution Explorer
    2. Нажмите кнопку Add Resource и выберите Add Existing File...
    3. Выберите изображения, которые хотите встроить. Я добавил group_box_top.png и group_box_top_left.png, которые отображаются в файле .resx как group_box_top и group_box_top_left.

Затем вы можете получить изображения из манифеста с помощью:

// 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. Add the files:
    1. Right-click on your project
    2. Go to Linker -> Input
    3. Добавьте файлы, которые хотите встроить, в свойство Embed Managed Resource File. Я добавил сюда PingSend.wav.

Чтобы получить доступ к файлам, просто выполните:

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

..который в этом случае загружает аудиофайл, готовый к воспроизведению.

person Jon Cage    schedule 20.07.2010

Я думаю, что путь к элементу ресурса должен быть полностью определен:

GetManifestResourceStream("MyNamespace.ImageResources.group_box_top_left")

Эта ссылка показывает пример C # (извините), обратите внимание, что при создании потока у него есть пространство имен в аргументах:

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

Это также касается того, как найти полный путь к ресурсу:

Как я могу узнать путь к встроенному ресурсу? < / а>

person Adam Houldsworth    schedule 19.07.2010
comment
Я действительно использовал код в вопросе, который вы связали, и он дал мне MyControlsLib.ImageResources.resources в соответствии с моими изменениями .. - person Jon Cage; 19.07.2010
comment
+1: Спасибо за предложения. Ни один из них не работал должным образом, но, по крайней мере, направил меня на правильный путь. - person Jon Cage; 20.07.2010