Встройте значки в приложение WPF как ресурс

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

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

Я заставил это работать с помощью следующего метода: http://dennisdel.com/?p=38

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

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

Какие-либо предложения?

11
задан BoltClock 7 October 2012 в 20:18
поделиться

1 ответ

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

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

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

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


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

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

  • Ресурсы Win32
  • "Встроенные ресурсы" NET Framework
  • Объекты CLR в наборе ресурсов
  • Ресурсы XAML
  • Ресурсы WPF (объекты в словаре ресурсов)

Ресурсы Win32

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

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

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

Вы можете просмотреть Win32 Resources в .exe или .dll, открыв сам .exe или .dll файл в Visual Studio, используя File -> Open.

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

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

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

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

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

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

Доступ к встроенным ресурсам осуществляется с помощью Assembly.GetManifestResourceStream и его родственников GetManifestResourceInfo и GetManifestResourceNames.

Встроенные ресурсы встраиваются в файлы .exe и .dll путем добавления файла в проект и установки действия сборки на "Embedded Resource".

Вы можете просмотреть встроенные ресурсы в файле .exe или .dll, открыв его в NET Reflector и заглянув в папку "Resources".

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

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

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

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

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

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

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

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

Ресурсы XAML

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

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

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

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

Ресурсы WPF в словаре ресурсов

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

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

Ресурсы WPF добавляются в ResourceDictionary путем добавления их в XAML-файл, содержащий 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 file:

<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).

27
ответ дан 3 December 2019 в 03:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: