Как сохранить файл из ресурсов c
Автор оригинала: mkyong.
В Java мы можем использовать getResourceAsStream или getResource для чтения файла или нескольких файлов из папки ресурсы или корневого каталога пути к классу.
Метод getResource возвращает URL и обычно преобразует его в Файл ; Не работает в файле JAR .
1. Файлы в ресурсах папка
1.1 Просмотрите файлы в src/main/ресурсы , позже мы получим доступ к файлам и распечатаем содержимое файла.
1.2 По умолчанию инструменты сборки, такие как Maven, Gradle или обычная практика Java, будут копировать все файлы из src/основные/ресурсы в корневой каталог целевые/классы или сборка/классы . Итак, когда мы пытаемся прочитать файл из src/main/ресурсы , мы читаем файл из корневого каталога пути к классам проекта.
1.3 Ниже приведена структура файла JAR. Обычно файлы в папке ресурсы копируются в корневой каталог пути к классу.
2. Получите файл из папки ресурсов.
2.1 Приведенный ниже пример демонстрирует использование getResourceAsStream и getResource методы чтения файла json/файл 1.json из папки ресурсы
- Метод getResource не работает в файле JAR.
- Метод getResourceAsStream работает везде.
2.2 Теперь мы упаковываем проект в файл JAR и запускаем его; на этот раз getResource завершится ошибкой и вернет либо Исключение NoSuchFileException , либо Исключение InvalidPathException . Мы не можем прочитать файлы внутри файла JAR по URL-адресу ресурса.
Запустите файл JAR в Linux (Ubuntu), он вызовет Исключение NoSuchFileException .
Запустите файл JAR в Windows, он вызовет Исключение InvalidPathException .
P.S В этом примере используется плагин Maven maven-jar-плагин чтобы создать файл JAR.
3. Получите файл из папки ресурсов – Модульный тест
3.1 Мы помещаем тестовые ресурсы в папку src/test/ресурсы для модульных тестов. Обычно файлы в тестовых ресурсах копируются в папку target/test-classes .
3.2 Это работает так же, как мы читаем файл из src/main/ресурсы . Мы используем то же самое getResourceAsStream и getResource методы чтения файла из src/test/ресурсов .
4. Получите все файлы из папки ресурсов. (Среда, ОТЛИЧНАЯ от JAR)
Если мы не знаем точного имени файла и хотим прочитать все файлы, включая файлы вложенных папок из папки ресурсов, мы можем использовать NIO Файлы.перейдите , чтобы легко получить доступ к файлам и прочитать их.
4.1 В приведенном ниже примере используются Файлы.пройдите чтобы прочитать все файлы из папки src/основные/ресурсы/json :
4.2 Однако стандартные Файлы.прогулка в примере 4.1 не удается получить доступ к файлам в файле JAR напрямую, попробуйте запустить пример 4.1 в среде JAR, и он выдает Исключение FileSystemNotFoundException .
Извлечение ресурсов из сборок
Класс ResourceManager предоставляет доступ к ресурсам во время выполнения. Вы можете использовать метод ResourceManager.GetString для извлечения строковых ресурсов и метод ResourceManager.GetObject или ResourceManager.GetStream для извлечения нестроковых ресурсов. Каждый метод имеет две перегрузки:
Перегрузка, единственным параметром которой является строка с именем ресурса. Метод пытается извлечь этот ресурс для языка и региональных параметров текущего потока. Дополнительные сведения см. в описании методов GetString(String), GetObject(String)и GetStream(String) .
Перегрузка, имеющая два параметра: строка с именем ресурса, а также объект CultureInfo , представляющий язык и региональные параметры, для которых требуется извлечь ресурс. Если не удается найти набор ресурсов для данной комбинации языка и региональных параметров, диспетчер ресурсов использует резервные правила для получения соответствующего ресурса. Дополнительные сведения см. в описании методов GetString(String, CultureInfo), GetObject(String, CultureInfo)и GetStream(String, CultureInfo) .
Диспетчер ресурсов использует процесс резервных ресурсов, чтобы управлять тем, как приложение извлекает ресурсы, связанные с языком и региональными параметрами. Дополнительные сведения см. в разделе "Процесс использования резервных ресурсов" в статье Упаковка и развертывание ресурсов. Сведения о создании экземпляра объекта ResourceManager см. в разделе "Создание экземпляров объекта ResourceManager" статьи о классе ResourceManager .
Пример извлечения строковых данных
В следующем примере вызывается метод GetString(String) для извлечения строковых ресурсов текущего языка и региональных параметров пользовательского интерфейса. Он включает нейтральный строковый ресурс для английского языка (США) и локализованные ресурсы для французского (Франция) и русского (Россия) языков и соответствующих региональных параметров. Следующий ресурс для английского языка (США) находится в файле Strings.txt:
Ресурс для французского языка (Франция) находится в файле Strings.fr-FR.txt:
Если текущая комбинация языка и региональных параметров пользовательского интерфейса относится к испанскому языку (Испания), обратите внимание, что пример отображает ресурсы на английском языке, так как ресурсы для испанского языка недоступны, а в примере английский язык задан по умолчанию.
Пример извлечения данных объекта
Для извлечения данных объекта можно использовать методы GetObject и GetStream . Сюда входят типы-примитивы, сериализуемые объекты и объекты, хранящиеся в двоичном формате (например, изображения).
Следующий код извлекает ресурс и отображает изображение в элементе управления PictureBox .
В следующем примере для десериализации настраиваемого объекта используется метод ResourceManager.GetObject(String) . Пример включает файл исходного кода UIElements.cs (UIElements.vb для Visual Basic), который определяет следующую структуру с именем PersonTable . Эта структура предназначена для использования подпрограммой общего отображения таблиц, которая отображает локализованные имена для столбцов таблиц. Обратите внимание, что структура PersonTable помечена атрибутом SerializableAttribute .
Следующий код из файла CreateResources.cs (CreateResources.vb для Visual Basic) создает файл ресурсов XML с именем UIResources.resx, где хранится заголовок таблицы, и объект PersonTable , содержащий сведения о приложении, локализуемые для английского языка.
После этого приведенный ниже код из файла GetObject.cs (GetObject.vb) извлекает ресурсы и выводит их на консоль.
Поддержка версий для вспомогательных сборок
Атрибут SatelliteContractVersionAttribute обеспечивает поддержку управления версиями для главной сборки. Указание этого атрибута для основной сборки приложения позволяет обновить и заново развернуть основную сборку без обновления ее вспомогательных сборок. После обновления основной сборки следует увеличить номер версии основной сборки, а номер версии вспомогательной сборки следует оставить без изменений. Когда диспетчер ресурсов извлекает запрошенные ресурсы, он загружает версию вспомогательной сборки, заданную этим атрибутом.
Сборки политик издателя обеспечивают поддержку управления версиями для вспомогательных сборок. Вы можете обновить и заново развернуть вспомогательную сборку без обновления основной сборки. После обновления вспомогательной сборки следует увеличить номер ее версии и доставить ее с помощью сборки политики издателя. В сборке политики издателя укажите, что новая вспомогательная сборка совместима с предыдущей версией. Диспетчер ресурсов будет использовать атрибут SatelliteContractVersionAttribute , чтобы определить версию вспомогательной сборки, но загрузчик сборок будет привязан к версии вспомогательной сборки, указанной в политике издателя. Дополнительные сведения о сборках политик издателей см. в разделе Создание файла политики издателя.
Чтобы включить полную поддержку управления версиями сборок, рекомендуется развернуть сборки со строгими именами в глобальном кэше сборок , а сборки без строгих имен — в каталоге приложения. Если вы хотите развернуть сборки со строгими именами в каталоге приложения, то при обновлении сборки не сможете увеличить номер версии для вспомогательной сборки. Вместо этого необходимо выполнить обновление на месте, при котором вы заменяете существующий код обновленным, сохраняя тот же номер версии. Например, если вы хотите обновить версию 1.0.0.0 вспомогательной сборки с полностью заданным именем "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a", перезапишите ее обновленным файлом myApp.resources.dll, скомпилированным с использованием того же полностью заданного имени сборки "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a". Обратите внимание, что использование обновления на месте для файлов вспомогательных сборок затрудняет приложению задачу по корректному определению версии вспомогательной сборки.
Дополнительные сведения об управлении версиями сборок см. в разделах Управление версиями сборок и Обнаружение сборок в среде выполнения.
Извлечение ресурсов из файлов RESOURCES
Если вы решили не развертывать ресурсы в вспомогательных сборках, то все равно можете воспользоваться объектом ResourceManager для прямого доступа к ресурсам из файлов RESOURCES. Для этого требуется развернуть файлы RESOURCES правильным образом. После этого используйте метод ResourceManager.CreateFileBasedResourceManager для создания экземпляра объекта ResourceManager и укажите каталог, содержащий автономные файлы RESOURCES.
Развертывание файлов RESOURCES
При внедрении файлов RESOURCES в сборку приложения и вспомогательные сборки все вспомогательные сборки имеют одинаковое имя файла, однако каждая из них помещается в подкаталог, который отражает ее язык и региональные параметры. И наоборот, при прямом доступе к ресурсам из RESOURCES-файлов все эти файлы можно поместить в один каталог, который обычно находится в каталоге приложения. Имя RESOURCES-файла по умолчанию для приложения состоит только из корневого имени без указания языка и региональных параметров (например, strings.resources). Ресурсы для каждого локализованного языка хранятся в файле, имя которого состоит из корневого имени, за которым следует обозначение языка и региональных параметров (например, strings.ja.resources или strings.de DE.resources).
На следующем рисунке показано, где должны находиться файлы ресурсов в структуре каталогов. На нем также приведены соглашения об именовании для файлов RESOURCE.
Использование диспетчера ресурсов
После создания ресурсов и помещения их в соответствующий каталог создайте объект ResourceManager , чтобы использовать ресурсы путем вызова метода CreateFileBasedResourceManager(String, String, Type) . Первый параметр указывает корневое имя RESOURCES-файла по умолчанию в приложении (в примере из предыдущего раздела этому соответствует "strings"). Второй параметр указывает расположение ресурсов ("Resources" в предыдущем примере). Третий параметр указывает используемую реализацию ResourceSet . Если третий параметр равен null , используется среда выполнения по умолчанию ResourceSet .
После его создания экземпляра объекта ResourceManager используйте методы GetString, GetObjectи GetStream для извлечения ресурсов, как было описано выше. Однако получение ресурсов непосредственно из RESOURCES-файлов отличается от извлечения внедренных ресурсов из сборок. При получении ресурсов из RESOURCES-файлов методы GetString(String), GetObject(String)и GetStream(String) всегда извлекают ресурсы для языка и региональных параметров по умолчанию, независимо от текущего их значения. Чтобы извлечь ресурсы для текущей или конкретной комбинации языка и региональных параметров приложения, необходимо вызвать метод GetString(String, CultureInfo), GetObject(String, CultureInfo)или GetStream(String, CultureInfo) и указать комбинацию языка и региональных параметров, ресурсы которой требуется получить. Чтобы получить ресурсы для текущего языка и региональных параметров, укажите значение свойства CultureInfo.CurrentCulture в качестве аргумента culture . Если диспетчер ресурсов не может извлечь ресурсы culture , для извлечения необходимых ресурсов он использует стандартные правила резервных ресурсов.
Пример
В следующем примере показано, как диспетчер ресурсов получает ресурсы непосредственно из RESOURCES-файлов. Пример состоит из трех текстовых файлов ресурсов для английского (США), французского (Франция) и русского (Россия) языков и соответствующих региональных параметров. В этом примере по умолчанию задан английский язык (США). Его ресурсы хранятся в файле с именем Strings.txt:
Ресурсы для французского языка (Франция) хранятся в следующем файле с именем Strings.fr-FR.txt:
Ниже приведен исходный код для этого примера. В примере создаются экземпляры объектов CultureInfo для английского языка (США), английского языка (Канада), французского языка (Франция) и русского языка (Россия), и каждый из этих языков делается текущим. Метод ResourceManager.GetString(String, CultureInfo) передает значение свойства CultureInfo.CurrentCulture в виде аргумента culture для извлечения подходящих ресурсов для конкретного языка и региональных параметров.
Любая программа в Windows это не только код, но еще и набор данных типа картинок, строк, значков, диалоговых окон и так далее. Все это хранится внутри .exe модуля программы в виде ресурсов. То есть, ресурсы в Windows можно рассматривать как вид данных, которые уже инициализированы.
Ресурсы не загружаются в память вместе со всей программой, а находятся на диске до тех пор, пока их не вызовет программа. Это позволяет не плодить на диске лишние микрофайлы и экономить оперативную память при выполнении приложения.
Ресурсы можно разделить на два типа: двоичные и текстовые. Двоичные ресурсы это обычно растровые картинки, иконки, курсоры. а текстовые ресурсы это строки, шаблоны диалоговых окон и т.п.
Ресурсы в проектах приложений Borland C++ Builder хранятся раздельно. Файл проекта с расширением .DFM содержит информацию о ресурсах окон и компонентов для конструирования самой формы приложением. Он создается автоматически при создании проекта и изменяется при добавлении компонентов на форму. Другой файл с расширением .res (Project1.res) - файл графических ресурсов - хранит курсоры, иконки и рисунки.
Для редактирования графических ресурсов Borland C++ Builder предусмотрен редактор Image Editor. Он позволяет редактировать битовые изображения (.bmp), пиктограммы (.ico), курсоры (.cur), а также сами файлы ресурсов (.res и .dcr).
Файлы ресурсов .rc также могут быть подключены к проекту Borland C++ Builder. При компиляции проекта информация из файлов .rc и информация на которую они ссылаются будет помещена в файл с расширением .res, а ресурсы из этого файла перенесены в .exe файл и становятся доступны приложению.
Каждый тип ресурсов имеет свой идентификатор. Полный список ресурсов можно посмотреть в файле winuser.h .
RT_ACCELERATOR - таблица ускорителей;
RT_ANICURSOR - анимированный курсор;
RT_ANIICON - анимированная икона;
RT_BITMAP - растровая картинка;
RT_DIALOG - диалоговое окно;
RT_FONTDIR - набор шрифтов:
RT_HTML - HTML документ;
RT_RCDATA - данные определенные приложением (RAW);
RT_STRING - таблица строк:
RT_VERSION - ресурс версия;
Таким образом - ресурсы это составная часть файлов .exe и .dll. Практически, при создании приложения, файлы ресурсов только переписываются в двоичном виде в .exe(.dll) файлы. Составляющие ресурсы извлекаются и используются по мере выполнения программы.
Для просмотра используемых приложением ресурсов можно использовать функцию WIN32 API EnumResourceTypes().
Поместим на форму один компонент TButton и определяем внешнюю функцию f_EnumFunc(), которая будет функцией перечисления:
В обработчике события нажатия кнопки TButton пишем код:
Цифры выдаваемые программой говорят о номерах ресурсов, которые использовал программист при ее написании.
.exe файл в ресурсах и его выполнение
Поставим целью спрятать в ресурсах создаваемого приложения некоторую другую программу, а в процессе выполнения приложения вызвать ее из ресурсов.
Поместим на форме компонент TMemo и два компонента TButton. В обработчике Button1Click напишем код:
Откомпилируем приложение, при нажатии кнопки Button1 в директории программы бедет содан файл со строчкой (которая отобразится в компоненте Memo):
Это строка "Имя ресурса | Тип ресурса | Имя программы" - полностью идентифицирует ресурс, а именно - программу calc.exe, которую можно будет спрятать в ресурсах приложения.
Далее, присоеденяем к проекту этот файл (Меню: Project/Add To Project.. выбираем a.rc файл).
Если сейчас попробовать откомпилировать проект, то компилятор выдаст ошибку. Причина - путь к calc.exe должен быть указан полный и, хотя ресурс еще не используется, но уже формируется. Поэтому скопируем calc.exe из директории Windows в директорию приложения (в противном случае необходимо указать полный путь).. Приложение компилирутся и можно начинать использовать ресурс. Удаляем файл "calc.exe" из директории проекта.
В обработчике Button2Click напишем код:
Здесь осуществляется выбор ресурса в поток - файла calc.exe (из файл "a.res", который уже создан). TResourceStream - потоковый класс, который обеспечивает доступ к компилируемым ресурсам в приложения. Он имеет множество методов для доступа к ресурсам, в том числе и для сохранения потока.
При нажатии на вторую кнопку калькулятор вызывается даже если его удалить не только из текущей директории приложения, но и из директории Windows.
Это не единственный способ вызова и запуска на выполнения .exe файла из ресурсов, но наиболее простой. Другие способы извлечения ресурсов и работы с потоками будут рассмотрены ниже - там где это или целесообразно, или другим способом задача не выполнима. При желании гурманы могут поэкспериментировать с TMemoryStream, WinExecute() и.т.п.
Текстовая информация в ресурсах
Помещение и извлечение текстовой информации, скопированной в ресурс из файла, и получение доступа к ней мало отличается от примера, описанного выше.
Создадим аналогичный проект с одним компонентом TMemo и двумя компонентами TButton. Шаги создания кода приложения будут аналогичны пройденным в предыдущем примере. Приведем лишь коды обработчиков событий нажатия кнопок.
Здесь одно отличие - тип ресурса вместо EXEFILE стал RT_RCDATA. После включения в проект файла "a.rc", не забудем поместить в дирректорию проекта любой файл readme.txt.
Последний обработчик имеет отличие от вызова программы связанное только с тем, что информация используется в самом приложении.
В результате при нажатии кнопки 2 файл "readme.txt" появляется в дирректории приложения (сколько его не удадяй) и отображается в компоненте Memo.
Картинки в ресурсах
Картинки можно поместить в ресурс как используя файл ресурсов проекта (project1.res) так и отдельный файл ресурсов, аналогично описанному выше хранению текста и программ.
Для рассмотрения первой возможности создадим новый проект и поместим на форму компонент TImage и два компонента TButton. В директорию проекта поместим любой рисунок в формате bmp (например "a.bmp") и откроем его в любом графическом редакторе, например в Microsoft Paint. Не компилируя проект запустим Image Editor (меню Tools/Image Editor). Далее откроем project1.res из директории проекта(File/Open, Projects/project1.res). Выполняем правый клик в поле открывшегося окна и в контекстном меню выбираем пункт New/Bitmap.
И сразу видим недостаток этого метода - максимальное число цветов для изображения - 256. Устанавливаем число цветов и размер (его определяем в Paint - меню Рисунок/Атрибуты). В файле у Contens появилась новая ветвь Bitmap с именем рисунка Bitmap1. (Можно воспользовавшись контекстным меню пунктом "Rename" и переименовать рисунок, например в MYBITMAP, но для наглядности делать этого не будем). Выполним двойной клик на имени рисунка - откроется окно редактора с пустым рисунком. Перенесем рисунок из Paint (ctrl+A, Ctrl+C) (можно и нарисовать свой рисунок в Image Editor) в окно Image Editor(ctrl+V). Закроем окно редактора рисунка и Image Editor, естественно на вопрос: "Save Changes. " кликнем "Yes".
Создадим обработчик нажатия для кнопки 2 и запишем несколько вариантов кода,позволяющего отображать и сохранять рисунок:
Откомпилируем и загрузим приложение, при нажатии кнопки 2 изображение появится в компоненте TImage.
Для рассмотрения использования отдельного файла ресурса в проект внесем некоторые изменения.
В обработчиках событий ButtonClick запишем коды, приведенные ниже. После компиляции и запуска приложения нажимаем первую кнопку и закрываем приложение. Добавляем к проекту файл "a.rc". Вновь компилируем и запускаем приложение и нажимаем вторую кнопку - картинка отображается в компоненте Image.
Пример полностью аналогичен предыдущему примеру, за исключением того, что для формирования файла .rc использован класс TStringList, а тип ресурса стал "RT_BITMAP".
Отображение рисунка возможно выполнить и немного по другому:
Редактирование картинок из ресурсов и отображение отредактированных картинок.
Следующие примеры показывают как можно извлекать ресурс картинки и внести в него коррективы. Зная структуру файла картинки, например, таким образом можно сделать надписи на картинках или наложить на рисунок из ресурса другой рисунок и т.п.
Тоже можно выполнить и чуть чуть по другому и с картинки из файла project1.res.
Иконки в ресурсах
Хранение иконок в ресурсах ничем не отличается от хранения рисунков.
Аналогично сначала используем иконку, поместив ее в ресурс через projekt1.res, а затем с использованием файла a.res.
Создадим новый проект на которой для данного примера достаточно поместить всего лишь два компонента Button. Не компилируя проект откроем projeсt1.res в Image Editor. Там уже есть веточка Icon с именем иконки MAINICON. Воспользовавшись контекстным меню пункт New/Icon, создаем новую иконку и переименуем ее в MAINICON1. Двойным кликом на имене иконки откроем графический редактор и нарисуем любой рисунок. Помним, что цвет левого нижнего пикселя является цветом прозрачности. Закроем редактор сохранив изменения в файле projeсt1.res.
Создадим обработчик нажатия для кнопки 2 и запишем следующий код:
Запускаем приложение. При нажатии кнопки 2 иконка меняется не только на форме окна приложения, но и в панели задач.
Следующий код показывает как можно получить информацию об иконке и как создается новая иконка, на основании структуры HICON. Кроме того здесь также показано как скопировать иконку в буфер обмена.
Структура ICONINFO общая для иконок и курсоров.
Для рассмотрения использования отдельного файла ресурса для работы с иконками в проект внесем некоторые изменения. В обработчиках событий ButtonClick запишем коды, приведенные ниже. После компиляции и запуска приложения нажимаем первую кнопку и закрываем приложение. Добавляем к проекту файл "a.rc". Вновь компилируем и запускаем приложение и нажимаем вторую кнопку - иконка меняется на нарисованную ранее (сохранена на предыдущем шаге) и в форме окна приложения, и в панели задач.
Курсоры в ресурсах
Использование ресурсов для манипуляций с курсорами во многом аналогично работе с иконками, но здесь есть и существенное отличие, речь о котором пойдет ниже.
Также как и ранее сначала создадим курсор в project1.res, а затем в файле a.res. Создадим новый проект на которой для данного примера поместим шесть компонент Button. Не компилируя проект откроем projeсt1.res в Image Editor. Так же как создавали иконку в предыдущем примере создадим курсор с именем MAINCURSOR и нарисуем его (любой рисунок, например черную стрелку). Закроем редактор сохранив изменения в файле projeсt1.res.
В секции private файла Unit1.h определим функцию vLoadCursor(). Эта функция необходима только для того, чтобы не повторять один и тотже код.
Тело функции опишем в файле "UNIT1.cpp" следующим образом:
Этот код показывает, что если удалось получить хэндл курсора, то его можно и подключить через массив Cursors свойств Screen. Об этом уже говорилось в разделе "Курсоры".
Создадим обработчик нажатия для кнопки 2 и запишем следующий код:
Откомпилируем и запустим приложение - нарисованный курсор появляется при нажатии на кнопку 2.
Для кнопки 3 создадим другой способ загрузки курсора.
Курсор загружается как и при нажатии на кнопку 2. О функции LoadImage() речь также уже шла.
Перейдем к использованию отдельного .res файла.
Для кнопки 1 напишем уже знакомый (новый только идентификатор ресурса RT_CURSOR) код:
Выполним этот код и в директории проекта будет создан файл "a.rc", содержащий строку:
На данном этапе отличия от предыдущего примера нет.
Скопируем в директорию проекта файл "Hand-i.cur" из директории "C:\Windows\Cursors\" и добавим к проекту файл "a.rc" (Project/Add to Project), а в обработчиках Button4Click напишем код:
При запуске приложения все работает, курсор формы сменился со стрелки на руку. Но как загрузить курсор не сохраняя его в файле на диске. До этого и иконки и картинки можно было загрузить и использовать прямо из потока. Для курсоров такой возможности нет.
Остается один выход - либо хранить курсоры только в Файле ресурсов приложения, либо пойти по достаточно сложному пути, который описан в обработчике события нажатия кноки пять (Button5Click).
Таким образом эта проблема решена. Но она к сожалению не одна, и хотя это может быть и не надо, все же попробуем сохранить курсор из Файла ресурсов приложения на диске, тоесть сохранить курсор MAINCURSOR.
Причина возникшей трудности в самом файле ресурсов приложения. Если откроем "project1.res" и "a.res" в редакторе ресурсов Image Editor, то увидим суть различия в достуре к курсорам.
Строки символов в ресурсах
По аналогии с предыдущими примерами поместим на форме компонент Memo и два компонента Button. В обработчиках ButtonClick напишем код:
Выполнив ту же последовательность действий как и в предыдущих примерах получим в компоненте Memo при нажатии кнопки два строку:
HTML документы в ресурсах
Помещение HTML документов (файлов .html, .htm . ) в ресурсы полностью аналогично с примером помещения в ресурсы и использования .exe файлов. Поэтому здесь приводятся лишь коды приложения, форма которого имеет компонент TMemo и два компонента TButton, и которое выводит в браузере документ "a.html", а текст кода документа в компоненте Memo.
.wav и другие музыкальные файлы в ресурсах
По аналогии с предыдущими примерами оформим создание файла a.rc для формирования a.res в приложении, поместив на форме компонент TButton. Откомпилируем и выполним приложение, предварительно поместив в директорию приложения любой музыкальный файл, например a.wav.
Заметим, что идентификатора ресурса SOUND нет в списке идентификаторов ресурсов. Это говорит о том, что в файл ресурсов можно помещать и произвольную информацию - вопрос лишь в том, как ее потом оттуда извлечь и использовать.
Добавим на форму еще один компонент TButton и запишем код:
Содержимое файла, помещенное в ресурс, воспроизводится дважды (для обеспечения этой возможности добавлен флаг SND_SYNC). Однако, если повторить все тоже, но заменив тип ресурса "SOUND", например на "SOUND1", эти функции откажутся воспроизводить ресурс. Таким образом, хотя "SOUND" не определен как тип ресурса в файле winuser.h как некоторая константа (например MAKEINTRESOURCE(x) - где x некоторое число), функции считают, что в исполняемом файле находится ресурс именно с типом "SOUND".
И всетаки, хотя в этом и нет необходимлсти, для приведенных ниже кодов ресурс может иметь любой идентификатор отличный от "SOUND". Здесь используются уже знакомые по предыдущим параграфам потоки, которые позволяют найти практически произвольный ресурс и извлечь его из исполняемого модуля как двоичный код.
Используем TMemoryStream и функции поиска и фиксации ресурса.
Аналогично .wav файлам можно манипулировать и с любыми другими музыкальными файлами.
Ресурсы в любом 32-битном исполняемом файле Windows 95/98/ME/NT/2000 (включая EXE, DLL, SCR, OCX и CPL) можно просмотреть, выбрав Файл→Открыть из главного меню Resource Hacker™. DLL-подобные файлы, такие как AX (ActiveMovie Proxy), FLT (Graphic Import Filter), HPA (Hewlett-Packard Printer Applet), PCI (Peripheral Component Interconnect), TSP (Microsoft Remote Service Provider) и VWP (Voxware MetaVoice Plug-In) можно также просмотреть. Полный список ресурсов файла будет отображаться в виде древовидной структуры. Дерево ресурсов может быть полностью развёрнуто или свёрнуто выбором пункта меню Вид→Развернуть всё или Вид→Свернуть всё соответственно.
Элементы ресурсов определяются его типом, именем и идентификатором языка.
Ресурсы сгруппированы в типах ресурсов. Существует несколько предопределённых типов ресурсов (icon, cursor, bitmap, dialog, menu, rcdata и т.д.), но программист также может задать другие типы ресурсов.
Элементы ресурсов находятся в пределах их соответствующих типов ресурсов и имеют имя ресурса, которое уникально в пределах этого типа. Это имя обычно либо целое число, либо текстовая строка; однако, некоторые типы ресурсов (например "String Table") позволяют только целые числа для имён.
Каждый именованный ресурс может иметь более одного определяемого языком элемента, что позволяет программе иметь несколько языков. Под каждым именем ресурса в дереве ресурсов находится хотя бы один элемент языкового ресурса. Идентификатор языка является текстовым значением целого числа сделанным из первичного (6 младших битов) и вторичного (10 старших битов) идентификаторов языка, который определяется Windows (если элемент языка нейтральный, то это значение равно 0).
Курсор и иконки
Курсоры и иконки требуют особого упоминания, так как информация их ресурса разделена между двумя типами ресурсов: "Cursor" & "Cursor Group"; и "Icon" & "Icon Group" соответственно.
Каждая иконка (или курсор) имеет несколько изображений (то есть группы связанных изображений иконок): 16x16 пиксель (16 цветов), 32x32 пиксель (16 цветов), 16x16 пиксель (256 цветов), и т.д. Изображение, которое фактически используется операционной системой зависит от затребованного размера (маленькая или большая иконка) и установленной глубины цвета монитора. Тип ресурса "Icon Group" содержит заголовочную информацию иконки - собственное имя изображения, а также его размер и глубину цвета. Однако фактически изображение хранится в типе ресурса "Icon".
Эта функция Windows API сначала находит заголовочную информацию для "Icon Group" ID 102. Затем, если более одной иконки перечислено в заголовочной информации, операционная система выбирает наилучшее изображение в списке.
Важно понимать, что при замене файловой иконки (или курсора) иконка целиком заменяется с заголовочной информацией (в "Icon Group") и всеми её собственными иконками (в "Icon").
Однако, оба варианта: одиночные иконки, и группы иконок могут быть извлечены из ресурса в файл-иконку (*.ico): если в дереве ресурсов выбран ресурс в типе "Icon", то иконка будет сохранена как одиночная. Если же выбран ресурс в типе "Icon Group", то все иконки, принадлежащие выбранному ресурсу будут сохранены в файл иконки.
Просмотр ресурсов
Просто выберите ресурс из дерева ресурсов (если файл был открыт). Ресурс будет отображаться в виде:
Комбинация декомпилированного текста и скомпилированной формы для предпросмотра
Данные в сыром виде (шестнадцатеричный слева и ASCII текст справа)
Примечание: Программы, скомпилированные с помощью Borland VCL (к примеру, многие программы на Delphi) обычно не имеют ресурсов Dialog, Menu или Accelerator, но хранят эту информацию в "RCData".
Извлечение (сохранение) ресурсов
Чтобы сохранить в файл все ресурсы определенного типа, выберите тип в дереве и затем выберите в меню Действие→Сохранить [ Тип ресурса ] ресурс . .
Чтобы сохранить все ресурсы в файл, выберите в меню Действие→Сохранить все ресурсы. . Ресурсы, которые не могут быть декомпилированы в текстовое представление ресурсов (как например изображения) будут преобразованы в свои собственные файловые форматы и сохранены в той же папке, что и текстовое представление ресурсов (например Cursor_1.cur, Cursor_2.cur, Bitmap_1.bmp, Icon_1.ico). Ресурсы с неопознанными форматами данных будут сохранены как *.bin файлы.
Модифицирование (замена) ресурсов
Во-первых, предупреждение или даже два:
Если вы собираетесь модифицировать ресурсы, то сначала сделайте резервную копию оригинального файла. В дальнейшем, тщательно проверяйте исправность нового файла. Чтобы облегчить эту операцию, всякий раз, когда файл изменен и сохранен, Resource Hacker™ будет автоматически делать резервную копию исходного файла (например в Explorer_original.exe) перед тем как сохранить.
В ресурсах Dialog и Menu, удаление элементов управления или изменение их идентификаторов, скорее всего, будет приводить к краху программы. Однако изменение надписей элемента управления, обычно безопасная операция, также как и изменение координат его расположения, размера и стилей отображения. Добавление нового элемента управления вряд ли вызовет проблемы. Переименование ресурсов также может привести к краху программы.
Использование встроенного редактора для изменения текстовых ресурсов:
Элементы управления ресурса Dialog могут быть изменены в размере и/или перемещены, и это автоматически сопровождается изменениями в текстовом представлении ресурса. Преобразование между пикселями экрана и единицами измерения диалога будет сделано автоматически.
Выберите элемент управления кликом на нём в отображаемом макете этого диалога. Кроме того, могут быть использованы клавиши Tab или Shift-Tab для выбора следующего или предыдущего элемента управления соответственно. Выбранный элемент управления будет обозначен маркерами изменения размера.
Чтобы переместить элемент управления без изменения размера, выберите его кликом мыши и перетащите в новое расположение. Клавиши со стрелками также можно использовать для перемещения элемента управления, когда он был выбран.
Элемент управления может быть изменен в размере путем нажатия и перетаскивания одного из его маркеров изменения размера. Кроме того, клавиши со стрелками с удерживаемой нажатой клавишей Shift могут быть использованы для изменения размера элемента управления.
Клавиша Escape ( Esc ) скрывает отображаемый макет диалогового окна.
Если элемент управления не может быть выбран кликом, то он, вероятно, перекрывается другим элементом управления. Элементы управления, которые объявлены в текстовом представлении ресурса ниже других элементов управления, на самом деле создаются в диалоговом окне выше своих предшественников (в порядке объявления в ресурсе) если на плоскости диалогового окна их расположения совпадают. Чтобы переместить или изменить размер перекрываемого элемента управления, нужно переместить или уменьшить размер перекрывающего элемента или изменить порядок объявления элементов управления в текстовом представлении ресурса. Редактор элемента управления (Control Editor) (см. ниже) также может быть использован для лёгкого изменения очерёдности следования элементов управления (см. поле "Z-порядок").
Редактор диалога может быть открыт из контекстного меню, появляющееся при клике правой кнопки мыши на элементе макета диалога. Редактор элемента управления (Control Editor) может быть открыт из того же контекстного меню.
Также могут быть добавлены новые элементы управления. Редактор элемента управления поддерживает практически все стандартные (Microsoft) и распространенные классы элементов. Пользовательские классы также могут быть добавлены во встроенный список классов, путём аккуратной правки текстового файла "Dialog.def", который находится в той же папке что и Resource Hacker™. Кнопки панели инструментов позволяют выбрать наиболее часто используемые элементы управления. Координаты левого верхнего угла элемента управления будут заполнены автоматически и эти значения будут соответствовать координатам, в которых было вызвано контекстное меню правой кнопкой мыши, чтобы открыть это диалоговое окно.
Замена изображений:
Если заменяемый ресурс является иконка, курсор или рисунок, источником могут быть файлы *.ico, *.cur или *.bmp соответственно, или выберите ресурсы из *.res или другого *.exe файла. Выберите в меню Действие→Заменить иконку (курсор / рисунок).
Замена ресурсов отличных от изображений:
Ресурсы отличные от изображений также могут быть заменены. Заменяемые ресурсы должны быть не только того же типа, но и с таким же именем ресурса. Выберите в меню Действие→Заменить другой ресурс . .
Примечание: Так как *.res файлы могут содержать множество ресурсов, то в диалоге добавления и замены ресурса отображается дерево ресурсов, так чтобы можно было выбрать конкретный ресурс в *.res файле. При добавлении или замене ресурсов из других типов файлов (не *.res), тип и имя ресурса должны быть введены вручную. Если поле "Язык ресурса" останется незаполненным, то предполагается нейтральный язык (0).
Обновление всех ресурсов ресурсами из *.res файла:
Также ресурсы могут быть заменены всеми совпадающими ресурсами, находящимися во внешнем *.res файле. Ресурс исходного файла (exe, dll) будет заменён ресурсом из внешнего *.res файла, только если он имеет такой же ресурс (тип, имя, язык). Выберите в меню Действие→Обновить все ресурсы . .
После всех проделанных модификаций файл можно сохранить, выбрав в меню Файл→Сохранить как .
Добавление ресурсов
Ресурс можно добавить в исполняемый файл, только если в нём нет ресурса с тем же типом, именем, языком. Выберите в меню Действие→Добавить новый ресурс . .
Добавление ресурсов позволяет программе поддерживать несколько языков.
(Примечание: Windows 95/98 не использует несколько языковых ресурсов, эта особенность WindowsNT. Я предполагаю, что Windows98 просто выбирает первый ресурс, если имеется более одного языкового ресурса.)
3. Сохраните ресурс в *.res файл (например "30757_french.res").
4. Закройте Samples.dll без сохранения и откройте его снова.
Dialog 30757 все ещё будет LANG_NEUTRAL, SUBLANG_NEUTRAL.
5. Выберите в меню Действие→Добавить новый ресурс и откройте файл "30757_french.res", который только что был создан.
6. Выберите Dialog 30757, который теперь имеет идентификатор языка 1036 (французский) и нажмите кнопку Добавить ресурс .
7. И наконец сохраните Samples.dll. Вуаля!
Подсказка: Изменение шрифта редактора Resource Hacker™ важно при просмотре или модификации ресурсов компилируемых в незападных языках (Выберите в меню Вид→Шрифт редактора. ).
Добавление иконок или рисунков (например логотип компании и т.п.) позволяет им быть отображёнными в диалоговых окнах программы.
В качестве примера:
* Задача: Добавить иконку в стандартное диалоговое окно "Открыть файл".
* Решение:
1. Откройте "C:\Windows\System\ComDlg32.dll".
(Ресурс диалога "Открыть файл" размещается в выше указанной DLL с именем ресурса 1547.)
2. Тип ‘Icon Group’ интересует тем, чтобы убедится, что имя добавляемой иконки в ‘Icon Group’ ещё не используется. В ComDlg32.dll имена иконок в диапазоне 528. 539, таким образом может использоваться любое другое целое число или строка из букв и цифр. (Не беспокойтесь об именах ресурсов, используемых в типе ‘Icon’, так как Resource Hacker™ обеспечит иконки уникальными именами.)
3. Добавьте иконку в dll, выбрав в меню Действие→Добавить новый ресурс . В диалоговом окне добавления ресурса, откройте файл, который содержит новую иконку и дайте иконке уникальное имя (например NEWICON).
4. В дереве ресурсов выберите Dialog, имя 1547. Предполагая, что новая иконка с именем "NEWICON", добавьте следующий элемент управления в конце списка элементов управления в текстовом представлении ресурса:
CONTROL "NEWICON",-1,STATIC, SS_ICON|WS_CHILD|WS_VISIBLE,13,142,21,20
5. Скомпилируйте изменения и сохраните файл как ComDlgXX.dll.
6. Системный файл ComDlg32.dll не может быть заменён в работающей Windows; его можно заменить только в режиме DOS. Вы можете сделать это вручную следующим образом:
7. Перезагрузите Windows и загрузите в режиме MS-DOS.
8. Используйте команды DOS, чтобы переименовать старый ComDlg32.dll к примеру в ComDlg98.dll и далее переименуйте вновь созданный файл в ComDlg32.dll.
9. Перезагрузите компьютер в Windows. На этом всё. (Конечно, добавление рисунка (bitmap) вместо иконки вызвало бы меньше замешательств, поскольку нет "Bitmap Group" для рисунков.)
Кроме того, вы можете сделать замену файла следующим образом:
7. Создайте в разделе HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager мультистроковый (REG_MULTI_SZ) параметр PendingFileRenameOperations и присвойте ему значение из 4-х строк:
\??\ C:\Windows\System32\ComDlg32.dll
! \??\ C:\Windows\System32\ComDlg98.dll
\??\ C:\Windows\System32\ComDlgXX.dll
! \??\ C:\Windows\System32\ComDlg32.dll
Формат этой записи следующий:
\??\ путь1_к_файлу_до_переименования
! \??\ путь1_к_файлу_после_переименования
\??\ путь2_к_файлу_до_переименования
! \??\ путь2_к_файлу_после_переименования
\??\ путь3_к_файлу_для_удаления
Windows автоматически обработает эту информацию и удалит этот параметр из реестра. Как вы заметили, в выше указанном примере показан формат удаления файла при загрузке, где вместо нового имени файла пустая строка. Так как в текстовом режиме пустые строки удаляются, то откройте параметр из контекстного меню, выбрав "Изменить двоичные данные" и введите 00 00 в области шестнадцатеричных данных.
Вот пример готового reg-файла.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager]
"PendingFileRenameOperations" = hex(7):5c,00,3f,00,3f,00,5c,00,43,00,3a,00,5c,00,\
57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,5c,00,53,00,79,00,73,00,74,00,65,\
00,6d,00,33,00,32,00,5c,00,43,00,6f,00,6d,00,44,00,6c,00,67,00,33,00,32,00,\
2e,00,64,00,6c,00,6c,00,00,00,21,00,5c,00,3f,00,3f,00,5c,00,43,00,3a,00,5c,\
00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,5c,00,53,00,79,00,73,00,74,00,\
65,00,6d,00,33,00,32,00,5c,00,43,00,6f,00,6d,00,44,00,6c,00,67,00,39,00,38,\
00,2e,00,64,00,6c,00,6c,00,00,00,5c,00,3f,00,3f,00,5c,00,43,00,3a,00,5c,00,\
57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,5c,00,53,00,79,00,73,00,74,00,65,\
00,6d,00,33,00,32,00,5c,00,43,00,6f,00,6d,00,44,00,6c,00,67,00,58,00,58,00,\
2e,00,64,00,6c,00,6c,00,00,00,21,00,5c,00,3f,00,3f,00,5c,00,43,00,3a,00,5c,\
00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,5c,00,53,00,79,00,73,00,74,00,\
65,00,6d,00,33,00,32,00,5c,00,43,00,6f,00,6d,00,44,00,6c,00,67,00,33,00,32,\
00,2e,00,64,00,6c,00,6c,00,00,00,00,00
if exist C:\Windows\WinInit.ini goto appendline
echo [rename] > C:\Windows\WinInit.ini
:appendline
echo NUL= %1 >> C:\Windows\WinInit.ini
Установите в свойствах ярлыка запуск со свёрнутым окном. Выберите ярлыку подходящую иконку корзины, например, одну из тех, что находятся в C:\Windows\System\Shell32.dll. -->
Читайте также: