Встраивать иконки в приложение WPF как ресурс - PullRequest
11 голосов
/ 11 июня 2010

Я пытаюсь встроить значок в мое приложение WPF, чтобы я мог извлечь его для использования в качестве значка в Windows 7 JumpList, используя следующий код:

newScene.IconResourcePath = System.Reflection.Assembly.GetEntryAssembly().Location;
newScene.IconResourceIndex = 0;

Я получилчтобы он работал, используя следующий метод: http://dennisdel.com/?p=38

Однако это не кажется лучшим подходом, и кажется, что должен быть более простой способ встроить ресурс значков в мое приложение, оставляя при этомОпция « Icon and Manifest » отмечена в свойствах приложения для моей программы.

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

Есть предложения?

1 Ответ

27 голосов
/ 11 июня 2010

В Visual Studio отсутствует способ запуска компилятора ресурсов Win32 из задачи MSBuild, и ни одна из его встроенных функций для создания ресурсов не создает необработанные ресурсы.По этой причине вы можете выбрать:

  1. Создать файл .res «вручную», как описано в связанной статье, или
  2. Добавить задачу сборки, чтобы можно было вызывать ресурс Win32.Компилятор из вашего .csproj

Сначала я объясню различия между пятью различными типами «ресурсов», которые могут существовать в файле .exe или .dll, включая «Ресурсы Win32», которые требуются JumpList.

Затем я объясню, как создать пользовательскую задачу сборки, которая позволяет встраивать произвольные ресурсы Win32 в исполняемый файл C # или VB.NET.


Пять видов ресурсов вИсполняемый файл Win32

Существует пять различных типов «ресурсов», которые могут существовать в файле .exe или .dll:

  • Ресурсы Win32 * Встраиваемые ресурсы
  • NET Framework "Ресурсы "
  • Объекты CLR в ResourceSet
  • Ресурсы XAML
  • Ресурсы WPF (объекты в ResourceDictionary)

Ресурсы Win32

Первоначальный вид ресурса был Win32 «Ресурс».Этот тип ресурса определен в файле .rc и имеет нумерованные или именованные ресурсы, каждый из которых имеет тип и блок данных.
Компилятор ресурсов Win32, rc.exe, компилирует файл .rc в двоичный файл .res, который затем может быть добавлен к полученному исполняемому файлу.

Доступ к ресурсам Win32 осуществляется с помощью Win32 FindResource и LoadResource functions.

Ресурсы Win32 встраиваются в приложения C ++, добавляя их в файл .rc, который компилируется в файл .res и связывается с исполняемым файлом.Их также можно добавить по факту с помощью программы rc.exe.Для приложений на C # и VB.NET MSBuild может добавить готовый файл .res к исполняемому файлу, который он создает с помощью компилятора Csc или Vbc, или может создать файл по умолчанию для вас.Ни в C #, ни в VB.NET нет возможности создавать файлы .res, отличные от заданных по умолчанию, из файлов .rc, и для этого нет задачи MSBuild.

Вы можете просматривать ресурсы Win32 в .exeили .dll, открыв сам файл .exe или .dll в Visual Studio с помощью команды Файл -> Открыть.

Типичное приложение на C, C ++ или MFC будет иметь много ресурсов Win32, например, будет указано каждое диалоговое окно.ресурсом.

Типичное приложение WPF будет иметь только три ресурса Win32 по умолчанию, созданные компилятором C # или VB.NET: ресурс версии, RT_MANIFEST и значок приложения.Содержимое этих ресурсов создается из атрибутов Assembly в коде и элемента <ApplicationIcon> в файле .csproj или .vbproj.

Это ресурс, который ищет JumpList.

Встроенные ресурсы

«Встроенный ресурс» - это ресурс NET Framework.Структура данных, содержащая эти ресурсы, управляется CLR более удобным способом для доступа через управляемый код.Каждый ресурс идентифицируется строковым именем, которое по соглашению начинается с пространства имен класса, с которым связан ресурс.

Встроенный ресурс - это просто двоичный объект двоичных данных с именем.Фактический тип данных либо известен вызывающему, либо выведен из имени, аналогично файлам в файловой системе.Например, встроенный ресурс с именем, оканчивающимся на «.jpg», скорее всего, будет файлом JPEG.

Доступ к встроенным ресурсам осуществляется с использованием Assembly.GetManifestResourceStream и его дочерних элементов GetManifestResourceInfo и GetManifestResourceNames. * 1063.*

Встроенные ресурсы встраиваются в файлы .exe и .dll, добавляя файл в проект и устанавливая для действия сборки значение «Встроенный ресурс».

Вы можете просматривать встроенные ресурсы в .exe или.dll, открыв ее в NET Reflector и просмотрев папку «Ресурсы».

Встроенные ресурсы обычно используются в WinForms, но почти никогда не используются в WPF.

Наборы ресурсов (.resx / .resources)

Несколько объектов NET Framework, таких как строки и значки, можно объединить в одно хранилище данных «Набор ресурсов», которое хранится в .exe в виде единого встроенного ресурса NET Framework. Например, это используется WinForms для хранения таких вещей, как значки и строки, которые нелегко включить в сгенерированный код.

Объекты в наборе ресурсов могут быть извлечены индивидуально с использованием классов ResourceManager и ResourceSet, определенных в CLR.

Объекты в наборе ресурсов определяются в исходном коде файлом .resx. Данные могут быть непосредственно в файле .resx (как в случае строк) или ссылаться на файл .resx (как в случае значков). Когда проект создается, содержимое, указанное в каждом файле .resx, сериализуется в двоичную форму и сохраняется как один встроенный ресурс с расширением «.resx», заменяемым на «.resources».

Вы можете просмотреть объекты в наборе ресурсов, открыв .exe или .dll в NET Reflector, открыв папку «Ресурсы», щелкнув файл «.resources» и посмотрев элементы в правой панели.

Многие функции эпохи WinForms обычно используют файлы .resx и ResourceSets аналогично старым файлам Win32 .rc для хранения нескольких ресурсов, таких как строки, вместе. Они также используются самой WinForms для хранения настроек в форме, которая не может быть в коде позади.

Приложения WPF почти никогда не используют произвольные объекты в ResourceSets, хотя сам WPF использует ResourceSets для внутреннего хранения скомпилированного XAML.

Ресурсы XAML

Ресурс XAML WPF - это скомпилированный файл XAML, который хранится в ResourceSet. Имя внутри набора ресурсов - это исходное имя файла, в котором «.xaml» заменено на «.g.baml». Содержимое может быть любым допустимым XAML, наиболее распространенными типами являются Window, Page, UserControl, ResourceDictionary и
Применение.

Ресурсы WPF можно загрузить с помощью Application.LoadComponent() или путем ссылки на исходное имя файла XAML в контексте WPF. Кроме того, любой ресурс WPF, имеющий код позади (как указано x:Class), будет автоматически загружен и применен к каждому объекту, созданному из этого класса во время его вызова InitializeComponent.

Ресурсы WPF создаются путем добавления файла .xaml в проект и установки для его действия по сборке «Ресурс», «Страница» или «ApplicationDefinition». Это заставляет компилятор скомпилировать файл в BAML и добавить его в соответствующий ResourceSet.

Вы можете просмотреть ресурсы XAML в .exe или .dll, открыв их в NET Reflector с установленной надстройкой BamlViewer, выбрав в меню Сервис -> BAML Viewer и используя BAML Viewer, чтобы перейти к конкретному. Файл g.baml внутри .resources.

Ресурсы WPF в ResourceDictionary

В WPF почти все из того, что известно как «ресурсы», являются записями в ResourceDictionary. ResourceDictionaries описаны в XAML, либо в других объектах, таких как Windows и UserControls, либо в отдельных файлах XAML, которые содержат только ResourceDictionary. Каждый из них обозначен «x: Key», который может быть любого типа объекта. Сами ресурсы также могут быть объектами любого типа.

На ресурсы

на WPF можно ссылаться в XAML с использованием расширений разметки {StaticResource} и {DynamicResource}, или их можно загружать в коде с использованием FindResource.

Ресурсы WPF добавляются в ResourceDictionary путем добавления их в файл XAML, который содержит ResourceDictionary внутри элемента <ResourceDictionary>, и присвоения им атрибута x:Key.

Ресурсы WPF широко используются в WPF, включая кисти, стили, данные, геометрию, шаблоны и т. Д.

Вы можете просматривать ресурсы WPF в .exe или .dll, просматривая ресурсы XAML, как описано выше, и для каждого, заглядывая в теги ResourceDictionary, чтобы увидеть сами ресурсы.


Включение ресурсов Win32 в исполняемый файл C # или VB.NET

Как легко встраивать произвольные ресурсы Win32 в C # или VB.NET .exe

Из приведенного выше обсуждения вы заметите, что легко добавить любой тип ресурса в ваше приложение на C # или VB.NET , за исключением для ресурсов Win32. Чтобы сделать это проще, вы можете добавить дополнительную задачу сборки и цель. Вот как:

  1. Создайте проект, содержащий одну задачу сборки "Win32ResourceCompiler", и скомпилируйте его
  2. Создайте файл .targets, содержащий одну цель, которая использует эту задачу для автоматического встраивания файла .rc в .res
  3. Настройте ваш проект на использование полученного файла .res

Задача предельно проста:

public class Win32ResourceCompiler : ToolTask
{
  public ITaskItem Source { get; set; }
  public ITaskItem Output { get; set; }

  protected override string ToolName { get { return "rc.exe"; } }

  protected override string GenerateCommandLineCommands()
  {
    return @"/r /fo """ + Output.ItemSpec + @""" """ + Source.ItemSpec + @"""";
  }

  protected override string GenerateFullPathToTool()
  {
    // TODO: Return path to rc.exe in your environment
  }
}

Файл .targets также очень прост. Это будет что-то вроде этого:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <UsingTask TaskName="SomeNamespace.Win32ResourceCompiler" AssemblyFile="Something.dll" />

  <PropertyGroup>
    <CoreCompileDependsOn>$(CoreCompileDependsOn);CompileWin32RCFile</CoreCompileDependsOn>
  </PropertyGroup>

  <Target Name="CompileWin32RCFile" Outputs="@(Win32RCFile->'%(filename).res')">
    <Win32ResourceCompiler
      Source="@(Win32RCFile)"
      Output="@(Win32RCFile->'%(filename).res')" />
  </Target>
</Project>

Теперь в вашем файле .csproj добавьте ссылку на ваш файл .targets:

<Import Project="Win32ResourceCompiler.targets" />

И, конечно же, вам нужно указать в файле .rc тип файла Win32RCFile:

<ItemGroup>
  <Win32RCFile Include="MyWin32Resources.rc" />
</ItemGroup>

С помощью этой настройки вы можете создать традиционный Win32 .rc файл, чтобы указать все ваши ресурсы Win32, включая вашу версию, манифест, значок приложения и столько дополнительных значков, сколько вы хотите. Каждый раз, когда вы компилируете, все эти ресурсы Win32 будут добавляться в ваш файл .exe.

Это займет немного времени для настройки, но в долгосрочной перспективе будет гораздо более приятным и простым, чем ручное редактирование файла .res.

Вы можете указать несколько значков в вашем файле .rc следующим образом:

1 ICON ApplicationIcon.ico
2 ICON JumpListIcon.ico
3 ICON AnotherIcon.ico

Здесь - документация для всех операторов определения ресурса, которые вы можете использовать в файле .rc.

Также обратите внимание, что вышеупомянутый файл .targets был набран под влиянием момента и не был протестирован. Документацию по синтаксису файлов MSBuild (.csproj и .targets) можно найти здесь и здесь , а хорошие примеры файлов .targets можно найти в каталоге c: \ Windows \ Microsoft.NET \ Framework \ v3.5).

...