Работа с двоичными ресурсами (.rc) в MS Visual C++ 2010 Express
Ресурсы - это бинарные данные, добавляемые в исполняемый файл при компоновке программы.1
В бесплатной MS Visual C++ 2010 Express редактор двоичных ресурсов отсутствует. Но это не беда, ведь ресурсы (и скрипты для них) можно создавать в сторонних редакторах. После этого их останется только импортировать в MSVC++ . Хороший пример такого редактора - программа Resource Editor by Anders Melander. О ней мы и расскажем в данной статье.
Содержание
- Работа с двоичными ресурсами (.rc) в MS Visual C++ 2010 Express
- Структура исполняемого PE-модуля (теория)
- Двоичные ресурсы исполняемых PE-файлов (тоже теория)
- Создаём базовое оконное приложение Windows
- Мутим двоичные ресурсы в MSVC+ + 2010 Express
- Организуем в нашем приложении оригинальные значки (иконки)
- Готовим значки
- Создаём скрипт ресурсов. Редактор ресурсов Resource Editor by Anders Melander.
- Добавляем resource.h (Проект Engine)
- Добавляем файл Resource01.rc в Проект WinTest01
- Изменения в Resource01.rc. Прописываем #include resource.h
- Изменения в WinMain.cpp . Прописываем #include resource.h
- Прописываем новые значки в структуре оконного класса
- Работа с кастомными (пользовательскими ресурсами)
- Организуем в нашем приложении оригинальные значки (иконки)
- Итоги
- Источники
Структура исполняемого PE-модуля (теория)
Сокращение PE расшифровывается как Portable Executable (от англ. "переносной исполняемый"). Данный формат пришёл из UNIX, где аналогичный формат назывался COFF (Common Object File Format - Стандартный формат объектных файлов). Microsoft подвергла COFF-формат значительной переработке и в теперешнем виде исполняемые PE-файлы используются в среде Windows повсеместно. В группу PE-файлов входят:
- Исполняемые файлы приложений Windows (.exe);
- Динамически подсоединяемые библиотеки (Dynamic Link Library - DLL);
- Объектные модули (obj);
- Драйверы режима ядра.
Любопытный факт
Сокращение MZ - это инициалы сотрудника компании Microsoft Марка Збиковски (Mark Zbikowscki), разработчика структуры исполняемых модулей в ОС MS-DOS.
После сигнатуры MZ в PE-модуле идёт стандартный заголовок MS-DOS, а далее - маленькая программа-заглушка, которая обычно выводит на экран консоли сообщение: "This programm cannot be run in DOS mode." ("Эта программа не может выполняться в MS-DOS."), после чего приложение завершает свою работу. Данный кусок кода часто называют stub (от англ. "заглушка").
Сразу после заголовков MZ и PE располагается таблица секций, состоящая из структур по 40 байтов каждая. Вот наиболее часто встречающиеся секции, генерируемые различными компиляторами:2
СЕКЦИЯ | ОПИСАНИЕ |
---|---|
.text | Секция содержит исполняемый код (Microsoft). |
CODE | Секция содержит исполняемый код (Borland). |
.data | Секция, содержащая инициализированные глобальные переменные (Microsoft). |
.bss | Все неинициализированные данные. Размер секции в файле равен нулю. |
.CRT | Секция, содержащая инициализированные данные (Microsoft). |
CRT | Секция, содержащая инициализированные данные (Borland). |
.rdata | Данные доступны только для чтения (константы, отладочная информация). |
По таблице секций можно вычислить положение секции в файле, её размер и, тем самым, получить возможность посмотреть, что в ней хранится.
Двоичные ресурсы исполняемых PE-файлов (тоже теория)
Форматы исполняемых файлов, используемых в Windows, позволяют хранить внутри них особые типы данных - ресурсы. К стандартным ресурсам Windows относятся:- Диалоговые окна (Dialog)
- Значки (Icons)
- Определения меню (Menu)
- Определения панелей инструментов (Toolbar)
- Растровые изображения (Bitmap)
- Курсоры мыши (Cursor)
Помимо редактора ресурсов, MS Visual C++ также включает в себя интерпретатор встроенного языка описания ресурсов. Его директивы можно увидеть, если открыть в текстовом редакторе, предварительно созданный в MS Visual C++, шаблон ресурсов (файл с расширением .rc).
Ресурсы можно создавать двумя способами:
- Описать ресурсы программы в текстовом ASCII файле с расширением RC. (Этот способ практически не используется.)
- Создать ресурс при помощи специализированного редактора ресурсов в режиме WYSIWYG (What You See Is What You Get - "Что видишь, то и получаешь").
Существуют также редакторы ресурсов от сторонних производителей (ResEdit, PE-Editor, Resource Workshop и др.). Все они имеют схожий функционал и пользовательский интерфейс, не требующий много времени на освоение.
- Стандартный (заменим значок на тулбаре);
- Кастомный (опишем и разместим внутри exe-шника рандомный двоичный файл).
Создаём базовое оконное приложение Windows
- В MS Visual C++ 2010 Express создай Проект базового оконного приложения WinTest01.
О том, где взять и как правильно установить MS Visual C++ 2010 Express, читай здесь: MS Visual Cpp 2010 Express. Установка и указание путей к DirectX SDK.
Обрати внимание
Напомним, что создаваемый проект изначально должен быть пустым, для чего ставится соответствующая галка в мастере (См. Рис.2).
Добавляем в Проект файл исходного кода WinMain.cpp
- Добавь в Проект WinTest01 файл исходного кода WinMain.cpp.
- Добавь в него исходный код из статьи Создание приложений Сpp Win32:
// Файл: WinMain.cpp // Описание: Шаблон оконного приложения Windows. Простейшее (базовое) приложение Windows, // выводящее на экран окно. // www.igrocoder.ru 2015 // При использовании просьба указывать ссылку на источник. #define STRICT #define WIN32_LEAN_AND_MEAN // Уменьшаем кол-во используемых компонентов в программе. #include <windows.h> // Прототип функции WinMain int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow); // Объявление оконной процедуры LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); // Реализация главной функции программы int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HWND hWnd; // Дескриптор окна MSG msg; // Структура сообщения WNDCLASSEX wndClass; // Объявляем экземпляр класса программы на базе WNDCLASSEX // Заполняем структуру оконного класса wndClass.cbSize=sizeof(wndClass); wndClass.style=CS_CLASSDC; // Поочерёдный доступ к контексту устройства (Device Context) wndClass.lpfnWndProc=WindowProc; // Оконная процедура wndClass.cbClsExtra=0; wndClass.cbWndExtra=0; wndClass.hInstance=hInstance; // Экземпляр окна wndClass.hIcon=LoadIcon(NULL, IDI_APPLICATION); // Пиктограмма приложения wndClass.hIconSm=LoadIcon(NULL, IDI_APPLICATION); // Малая пиктограмма приложения wndClass.hCursor=NULL; // Курсор при наведении на окно wndClass.hbrBackground=NULL; // Закрашиваем окно белым цветом wndClass.lpszMenuName=NULL; // Дескриптор Главного меню окна. Сейчас оно не нужно wndClass.lpszClassName="GameClass"; // Обзываем оконный класс. // Если класс не зарегистрируется, досрочно прерываем выполнение программы if(!RegisterClassEx(&wndClass)) return FALSE; // Создание окна на основе зарегистрированного класса hWnd=CreateWindow( "GameClass", // Класс окна. "My game title", // Текст заголовка (на верхнем тулбаре). WS_OVERLAPPEDWINDOW, // Обычное окно с кнопками в правом верхнем углу. 0, 0, // Координаты X и Y GetSystemMetrics(SM_CXSCREEN), // Ширина окна GetSystemMetrics(SM_CYSCREEN), // Высота окна NULL, // Дескриптор родительского окна NULL, // Дескриптор меню hInstance, // Дескриптор экземпляра приложения NULL); // Дополнительные данные if(hWnd==NULL) return(FALSE); // Собственно, показываем окно ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); // Очищаем структуру сообщения ZeroMemory(&msg, sizeof(MSG)); // Процедура выборки сообщений // Продолжаем бесконечно, пока не получим сообщение WM_QUIT (завершение). while(msg.message != WM_QUIT) { // Просмотрим очередь: вдруг там ожидает сообщение... if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // Есть сообщение! Обработаем его как обычно... TranslateMessage(&msg); DispatchMessage(&msg); } else { // Нет сообщений, ожидающих обработки. // Значит приступим к выполнению критичных ко времени операций. // Например, займёмся рендерингом. } } //Удаляем регистрацию класса UnregisterClass("GameClass", hInstance); // Выходим из приложения return (msg.wParam); } // Оконная процедура LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_DESTROY: // В случае этого сообщения... PostQuitMessage(0); // Говорим Windows закрыть приложение break; // В случае любых других сообщений... default: return DefWindowProc(hWnd, msg, wParam, lParam); } return 0; }
- Сохрани Решение/Проект (Файл -> Сохранить все).
Готовим Проект WinTest01 к компиляции
Для успешной компиляции Проекта WinTest01 изменим пару его свойств.Устанавливаем многобайтовую кодировку (multibyte encoding)
Примечание
В MS Visual C++ 2010 в настройках по умолчанию стоит набор (кодировка) символов UNICODE. В MS Visual C++ 6.0 - напротив, по умолчанию стоит кодировка ANSI (многобайтовая). Данная настройка сильно влияет на типы используемых переменных, что приводит к заметным различиям в исходном коде.
Несмотря на то, что во всех случаях рекомендуется использовать кодировку UNICODE, поддерживаемую во всех современных ОС семейства MS Windows (начиная с Win 2000/XP), большинство книг по программированию игр на классическом C++ придерживаются именно многобайтовой кодировки. Чтобы сильно не переделывать исходные коды под UNICODE, данный Проект мы настроим под многобайтовую кодировку.
Для этого...
- В Обозревателе решений щёлкаем по названию только что созданного Проекта WinTest01.
- Во всплывающем меню выбираем "Свойства"
- В появившемся окне установки свойств Проекта жмём "Свойства конфигурации", в правой части в строке "Набор символов" выставляем значение "Использовать многобайтовую кодировку".
- Жмём ОК.
Отключаем инкрементную компоновку (incremental linking)
Иначе при компиляции возможны ошибки вроде этой:Error LNK1123: сбой при преобразовании в COFF: файл недопустим или поврежден
- В Главном меню MS Visual C++ 2010 выбираем Проект -> Свойства.
- В появившемся окне установки свойств Проекта жмём Свойства конфигурации -> Компоновщик -> Общие (Configuration Properties -> Linker -> General), в правой части в строке "Включить инкрементную компоновку" ставим значение "Нет (/INCREMENTAL:NO)".
- Жмём ОК.
- Сохрани Решение/Проект (Файл -> Сохранить все).
Удаляем файл cvtres.exe
В нашем случае (Win7 x64) полный путь до данного файла такой: C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\cvtres.exeВ Win32-кодинге он особо ни на что не влияет. Зато без него линковка идёт как по маслу.
Компилируем Проект Test01
Проект готов к компиляции.- Скомпилируй Проект/Решение (кнопка с зелёным треугольником на Панели инструментов MSVC++ или <F5> на клавиатуре).
Если весь код был введён без ошибок, после компиляции запустится приложение, отображающее окно с белым фоном.
Мутим двоичные ресурсы в MSVC+ + 2010 Express
Продолжаем работать с Проектом WinTest01.Организуем в нашем приложении оригинальные значки (иконки)
У каждой игры есть стартовый (запускной) .exe файл, который в Проводнике Windows отображается с оригинальным значком с логотипом игры. В каждом таком приложении, как правило, используется два значка, в исходном виде представляющие собой растровые изображения с расширением .ico:- Значок размером 32х32 точек, отображаемый в Проводнике Windows.
- Уменьшенная копия первого значка размером 16х16 точек, отображаемая на тулбаре (верхней полоске) окна приложения.
Готовим значки
Оба значка можно без труда создать и экспортировать в файл формата .ico в любом графическом редакторе (в идеале Photoshop). Битность может быть любая, но желательно не больше 8-битной палитры (256 цветов). Часто оба значка выглядят одинаково, но отличаются лишь размером.В нашем случае мы нашли готовое ICO-изображение в Интернете по запросу "ico 32x32". Скачанный файл почему-то оказался больше - 128x128 пикселей.
- Открой скачанный файл в любом графическом редакторе.
- В нём поочерёдно измени размер изображения (Изображение -> Изменение размера... ):
- сначала до размеров 32х32, пересохранив результат как Test01.ico,
- затем до размеров 16х16, пересохранив результат как Test01_sm.ico.
Напомним, для дальнейшей работы нам требуется 2 значка размером 16х16 и 32х32.
- Подготовь два значка размером 16х16 и 32х32.
- Скопируй оба значка в каталог с текущим Проектом WinTest01.
Создаём скрипт ресурсов. Редактор ресурсов Resource Editor by Anders Melander.
Просто добавить значки в Проект WinTest01 не получится. Сперва необходимо их описать в специальном скрипте ресурсов, представляющем собой обычный текстовый файл с расширением .rc . Напомним, в бесплатной MSVC++2010 Express редактор ресурсов вырезан напрочь. Поэтому для создания скрипта ресурсов воспользуемся сторонним приложением Resource Editor by Anders Melander (далее - Resource Editor by AM). Далее в этой статье будем работать только в ней. В разделе Софт нашего сайта ты найдёшь и другие редакторы двоичных ресурсов. Все они имеют во многом схожий интерфейс и поддерживают сохранение макета в файл шаблона ресусов (.rc).
- Скачай программу Resource Editor by AM например отсюда: https://portablerus.myblog.ws/localization-tools/resource-editor-0-9-0-834
- Перейди в каталог с программой и запусти ResourceEditor.exe .
Быстро пробежимся по её интерфейсу:
ПАНЕЛЬ ИНТЕРФЕЙСА | ОПИСАНИЕ |
---|---|
Свойства (Properties) | Похож на редактор свойств в IDE от Borland и Microsoft. Активируется сразу после создания ресурса. В двухколоночной таблице в формате Свойство - Значение. Редактируем свойства активного (=выбранного в данный момент или только что созданного) ресурса/элемента управления. У разных ресурсов разные свойства. Но есть и общие: ID, Name, Language и т.д. |
Ресурсы (Resources) | Древовидный список ресурсов (например, открытого .exe-файла). Ресурсы группируются по типу. При клике ЛКМ по ресурсу в панели Свойства отображаются его свойства, доступные для редактирования. Ресурсы могут быть добавлены, удалены, экспортированы, сохранены. |
Варианты (Variants) | Показывает различные варианты ресурса. Любой ресурс может иметь только 1 ID, но несколько вариантов на разных языках, с разной глубиной цветности или размерами. |
Preview | Предварительный просмотр ресурса (например, курсора). Любопытно, что Resource Editor by AM умеет отображать в этой панели видеоролики и HTML-документы (если есть). |
Edit | Редактор ресурсов. Здесь мышью перемещаем элементы диалогового окна или просто перерисовываем курсоры/значки. Ресурсы неизвестного типа отображаются здесь в виде HEX-кода или текста. Чтобы не уходить от темы (создание скрипта ресурсов) сам встроенный редактор значков (иконок) здесь не рассматриваем. Там всё просто. При желании разберёшься сам. |
Напомним, для описания двух значков нам требуются два файла:
- Resource01.rc
- resource.h
- В Resource Editor by AM На панели Ресурсы жмём правой кнопкой мыши (ПКМ) по рабочей области. В контекстном меню выбираем "Добавить из файла".
- В диалоговом окне выбираем Test01.ico .
- Активируй добавленный значок в окне Ресурсы ЛКМ. В панели Свойства смени ID значка на IDI_ICON1.
- Аналогичным образом добавь Test01_sm.ico и смени его ID на IDI_ICON2.
- Сохрани скрипт ресурса в файл Resource01.rc в каталог с Проектом WinTest01.
В главном меню: Файл -> Сохранить как... Укажи имя Resource01. Во всплывающем списке выбери расширение .rc и жми Сохранить.
- Открой сохранённый файл Resource01.rc в любом текстовом редакторе. Ознакомься с его содержимым.
Добавляем resource.h (Проект Engine)
В заголовочном файле resource.h перечисляются ID-идентификаторы ресурсов.ОК, приступаем.
- Стартуй MSVC++ 2010 и открывай Решение GameProject01 (если не сделал это раньше).
- В "Обозревателе решений" главного окна MSVC++2010 щёлкни правой кнопкой мыши по папке (в терминологии Майкрософт это не папки, а фильтры!) "Заголовочные файлы" Проекта Engine.
- Во всплывающем меню Добавить->Создать элемент... (Add->New Item...)
- В появившемся окне выбери "Заголовочный файл (.h)" и в поле "Имя" введи "resource.h" (Да, именно с маленькой буквы! Так требует MSVC++.).
Добавленный файл сразу откроется в правой части MSVC++2010.
- В только что созданном и открытом файле resource.h набираем следующий код:
#define IDI_ICON1 101 #define IDI_ICON2 102
Невероятно, но факт!
В конце листинга Resource.h обязательно оставь пустую строку, перенеся каретку ввода на следующую строку. В противном случае при компиляции MS VC++ выдаст ошибку! Природа подобных "Фэн-шуй наклонностей" никому неизвестна.
Как видим, нашим значкам были присвоены символьные идентификаторы IDI_ICON1 и IDI_ICON2. Они-то и нужны для загрузки значков в приложение.
В принципе всё. Скрипт ресурсов Resource01.rc и сопутствующий заголовок resource.h готовы. Осталось добавить Resource01.rc в Проект WinTest01 и кое-что прописать в коде.
Добавляем файл Resource01.rc в Проект WinTest01
- Стартуй MSVC++2010 Express, если не сделал этого раньше. Открой Решение/Проект WinTest01, созданное выше.
- В Обозревателе решений щёлкни правой кнопкой мыши по "папке" (Напомним, что в терминологии Microsoft это не папки, а фильтры!) "Файлы ресурсов".
- Во всплывающем контекстном меню выбери Добавить->Существующий элемент.
- В появившемся окне выбора файла выбери файл скрипта ресурсов Resource01.rc и нажми "Добавить".
Изменения в Resource01.rc. Прописываем #include resource.h
- Перейди в каталог Проекта WinTest01 и открой Resource01.rc в любом текстовом редакторе.
- Найди следующий фрагмент:
... #define APSTUDIO_READONLY_SYMBOLS #define APSTUDIO_HIDDEN_SYMBOLS #include "windows.h" ...
- Строкой ниже добавь директиву
#include "resource.h"
- Сохрани изменения в Resource01.rc .
Изменения в WinMain.cpp . Прописываем #include resource.h
- В начале листинга WinMain.cpp найди список подключаемых заголовочных файлов (include-строки):
#define STRICT #define WIN32_LEAN_AND_MEAN // Уменьшаем кол-во используемых компонентов в программе. #include <windows.h> ...
- Добавь чуть ниже строку :
#include "resource.h"
- Сохрани Решение (Файл->Сохранить всё).
Прописываем новые значки в структуре оконного класса
- В WinMain.cpp найди следующий фрагмент:
... // Реализация главной функции программы int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HWND hWnd; // Дескриптор окна MSG msg; // Структура сообщения WNDCLASSEX wndClass; // Объявляем экземпляр класса программы на базе WNDCLASSEX // Заполняем структуру оконного класса wndClass.cbSize=sizeof(wndClass); wndClass.style=CS_CLASSDC; // Поочерёдный доступ к контексту устройства (Device Context) wndClass.lpfnWndProc=WindowProc; // Оконная процедура wndClass.cbClsExtra=0; wndClass.cbWndExtra=0; wndClass.hInstance=hInstance; // Экземпляр окна wndClass.hIcon=LoadIcon(NULL, IDI_APPLICATION); // Пиктограмма приложения wndClass.hIconSm=LoadIcon(NULL, IDI_APPLICATION); // Малая пиктограмма приложения wndClass.hCursor=NULL; // Курсор при наведении на окно wndClass.hbrBackground=NULL; // Закрашиваем окно чёрным цветом wndClass.lpszMenuName=NULL; // Дескриптор Главного меню окна. Сейчас оно не нужно wndClass.lpszClassName="GameClass"; // Обзываем оконный класс. ...
- Строку wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); замени на
wndClass.hIcon=LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
- Строку wndClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); замени на
wndClass.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON2));
- Сохрани Решение (Файл->Сохранить всё).
Обрати внимание
Если до этого в первом параметре функции LoadIcon стояло NULL (идентификатор экземпляра окна), то теперь мы прописали текущий экземпляр (инстанс) hInstance. Без этого тоже компилируется, но значок в заголовке выводится в виде знака вопроса.
Макрос MAKEINTRESOURCE конвертирует имя ресурса в строковой указатель (string pointer), который требуют многие функции.
- Скомпилируй Решение/Проект(F5).
Работа с кастомными (пользовательскими ресурсами)
Как мы уже говорили, что помимо стандартных ресурсов (значки, меню, строки и т.д.), MSVC++ также поддерживает загрузку и использование нестандартных ресурсов, например игровых карт (level maps).Подготовка кастомного (нестандартного) ресурса
Вновь работаем с ResourceEditor by AM. Тот же проект со значками.Предположим, что нашим кастомным ресурсом будет игровая карта. Парсить мы её сейчас, конечно, не будем. И вообще, карты не компилируют вместе с exe-шником. Важно усвоить сам принцип.
- Найди и скачай в Интернете по запросу "Quake 2 maps" любую карту.
- Открой архив, например, программой 7-Zip и распакуй из него 187city_w.bsp из подкаталога maps в каталог с Проектом WinTest01.
В программе ResourceEditor by AM:
- В панели Ресурсы щёлкни правой кнопкой мыши (ПКМ).
- Во всплывающем меню выбери Добавить из файла.
- В появившемся диалоге выбери файл 187city_w.bsp.
Видим, что по умолчанию ему присвоено ID 187CITY. В идеале картовый ресурс желательно переименовать по общепринятым правилам.
В панели Ресурсы выдели ресурс карты щелчком ЛКМ.
- В панели Свойства измени ID ресурса с 187CITY на IDR_187city. Жми OK.
- Сохрани ResEdit-проект (Файл->Сохранить).
Type: RCDATA
- Смени тип на BSP_MAP.
Кастомный ресурс добавится в общем списке в панели Ресурсы. Resource Editor разместил его в "ветке" bsp_map, согласно указанному нами типу.
- Сохрани Resource Editor-проект (Файл->Сохранить).
- Открой Resource01.rc в любом текстовом редакторе.
- Добавь недостающую директиву #include "resource.h" .
- Сохрани изменения.
- Добавь в resource.h строку #define BSP_MAP 103:
#define IDI_ICON1 101 #define IDI_ICON2 102 #define BSP_MAP 103
Перекомпилируем Проект Test01
Обновив всего 2 файла (Resource01.rc и resource.h) с помощью Resource Editr by AM и программы Блокнот, мы можем смело отправлять Проект WinTest01 на перекомпиляцию! При этом ни один из ресурсов даже не был добавлен в MSVC++2010. Всё делалось через однажды указанный скрипт ресурсов Resource.rc .- Стартуй MSVC++2010 Express, если не сделал этого раньше. Открой Решение/Проект WinTest01, созданное выше.
- Перекомпилируй Проект WinTest01 (ПКМ по названию Проекта WinTest01 -> Перестроить).
Применение кастомного ресурса в коде приложения
После включения (посредством скрипта ресурсов) кастомного ресурса в Проект Test01 (и размещения внутри исполняемого файла приложения), мы можем получить к нему доступ из исходного кода через его (ресурса) указатель, который получают с помощью одной из трёх специальных функций:3Таблица 1. Функции для работы с ресурсами
ФУНКЦИЯ | ОПИСАНИЕ |
---|---|
FindResource | Ищет прикреплённый к исполняемому .exe-файлу ресурс и возвращает его дескриптор (handle). |
LoadResource | Загружает прикреплённый к исполняемому .exe-файлу ресурс в глобальную область памяти и возвращает его дескриптор (handle). |
LockResource | Блокирует (locks) участок памяти с размещённым в нём ресурсом и возвращает указатель (memory pointer) на него. |
Функция FindResource... Вот её прототип:
HRSRC FindResource( HMODULE hModule, // Указатель на модуль ресурсов, обозначенный в WinMain. LPCSTR lpName, // Имя ресурса. LPCSTR lpType // Тип ресурса. );
...находит ресурс в блоке ресурсов исполняемого .exe-файла и возвращает его дескриптор (handle), который затем использует функция LoadResource. Параметр hModule представляет собой указатель на экземпляр (instance handle), получаемый от функции WinMain. lpName - имя ресурса (например IDR_MAP1). lpType - имя типа ресурса (например GameMaps). Как мы видели в программе ResEdit ресурсы каждого типа помещаются в отдельную папку-фильтр.
Функция LoadResource загружает ресурс в память и возвращает ещё один дескриптор, в этот раз для использования в функции LockResource.
GLOBAL LoadResource( HMODULE hModule, // Указатель на модуль ресурсов, обозначенный в WinMain. HRSRC hResInfo // Дескриптор (handle) из вызова функции FindResource. );
Вызовы функций FindResource и LoadResource можно комбинировать в один:
HGLOBAL hResource = LoadResource(hInstance, FindResource(hInstance, MAKEINTRESOURCE(IDR_MAP1), "GameMaps"));
Функция LockResource принимает всего 1 параметр - дескриптор (handle), полученный от функции LoadResource:
LPVOID LockResource(HGLOBAL hResData);
Дескриптор, возвращаемый функцией LockResource представляет собой void-указатель, который затем можно транслировать (cast) в любой тип данных.
В качестве примера загрузки кастомного ресурса возьмём текстовый файл readme.txt и зададим ему пользовательский тип ресурсов TEXT. Допустим, имя данного ресурса IDR_TEXT1. Данный фрагмент кода загружает ресурс в память и выводит содержимое текстового файла во всплывающем окне сообщений (Message box):
HGLOBAL hResource = LoadResource(hInst, FindResource(hInst, MAKEINTRESOURCE(IDR_TEXT1), "TEXT")); if(hResource!=NULL) { char *pText = (char*)LockResource(hResource); MessageBox(NULL, pText, "Text", MB_OK); }
Итоги
Урезанность бесплатной MS Visual C++ 2010 - не помеха. Раздобыв дополнительную бесплатную программу по созданию ресурсов Resource Editor by AM, мы запросто можем "подсунуть" нашей IDE практически любой готовый ресурс.Источники
2. Пирогов В.Ю. Ассемблер и дизассемблирование. - СПб.: БХВ-Петербург, 2006
3. Adams J. Programming Role Playing Game in DirectX 8.0 - Premier Press, 2002
Последние изменения страницы Воскресенье 24 / Июль, 2022 04:54:43 MSK
Последние комментарии wiki