В большинство
программ Windows включаются пиктограммы,
используются окна меню и диалога,
различные курсоры. Все это виды ресурсов
(resource) Windows.
Внешний вид ресурса
задают шаблоном. Шаблон можно описать
тремя способами:
-
Включая текст
описания шаблона в файл ресурсов
приложения. Для изменения внешнего
вида ресурса достаточно редактировать
файл ресурсов, не изменяя текста
приложения. -
Используя редактор
ресурсов интегрированной среды
разработки приложения. Эти редакторы
позволяют с помощью мыши и клавиатуры
нарисовать ресурс и сохранить текст
описания шаблона в файле ресурсов. -
Создавая шаблон
в памяти в процессе работы приложения.
Приложение в зависимости от содержания
требуемых и предоставляемых данных и
способа обмена изменяет вид ресурса.
С ростом потребности оперативного
обмена данными с различными источниками
информации этот способ находит все
более широкое применение.
Файлы ресурсов
приложения
Файлы ресурсов
представляют собой одну из самых
характерных особенностей программирования
в Windows, а именно
-
С помощью файлов
ресурсов большинство приложений
определяют визуальные элементы своего
пользовательского интерфейса: меню,
диалоговые окна, надписи, растровые
изображения и другие типы ресурсов. -
Файлы ресурсов
(rc-файлы) создаются в виде текстового
файла (этот файл можно создать как
текстовым редактором, так и специальным
редактором ресурсов) и компилируются
компилятором ресурсов. Полученный в
результате двоичный файл (res-файл) обычно
компонуется с оставшимися частями
приложения, образуя единый двоичный
образ, содержащий выполняемый программный
код и информацию о ресурсах. -
На финальном этапе
сборки загрузочного модуля компилятор
ресурсов вызывается еще раз для записи
ресурсов в загрузочный модуль. Также
он формирует специальную таблицу
ресурсов, расположенную в заголовке
exe-файла. Таблица используется Windows для
поиска и загрузки ресурсов в оперативную
память. -
Ресурсы являются
данными, и они хранятся в exe-файле
программы, но расположены они не в
области данных, где обычно хранятся
данные исполняемых программ. Таким
образом, к ресурсам нет непосредственного
доступа через переменные, определенные
в исходном тексте программы. Они должны
быть явно загружены из exe-файла в память.
Ресурсы не обязательно
должны компоноваться с исполняемым
файлом приложения, они также могут
сводиться в отдельную библиотеку DLL.
Преимущество этого подхода заключается
в том, что при изменении файла ресурсов
не требуется перекомпилировать все
приложение, а нужно только заменить
DLL.
Компоненты файла
ресурсов
Файл ресурсов или
сценарий ресурсов может содержать любое
количество утверждений сценария ресурсов
и директив препроцессора. Рассмотрим,
например, простой файл ресурсов:
#include <windows.h>
DlgBox DIALOG 20,20,200,200
STYLE
DS_MODALFRAME|WS_CAPTION|WS_SYSMENU
CAPTION “SampleDialog”
BEGIN
DEFPUSHBUTTON “Sample
Button”,IDOK,20,45,50,15,WS_GROUP
CTEXT
“Sample Message”,-1,10,10,90,8
END
Этот простой сценарий
определяет диалоговое окно с одной
кнопкой и одним статическим полем (с
надписью). Из приложения, использующего
такой ресурс, можно сослаться на это
диалоговое окно по имени DlgBox.
Хотя это и не очевидно
с первого взгляда, некоторые константы
(например, IDOK, DS_MODALFRAME или WS_GROUP) определены
в файле windows.h и не являются частью языка
сценария ресурсов. Директива #include в
стиле С/C++ используется для указания
файла, содержащего макроопределения.
Обычно оператор
файла ресурсов состоит из идентификатора,
который может быть или текстовой строкой
(надписью, как DlgBox в предыдущем примере),
или числовым значением, за которым
следует сам оператор.
Оператор может
состоять из одной строки (в таком случае
за ним следует один или несколько
параметров) или из многих строк (в этом
случае за оператором следует блок
инструкций).
В дальнейшем будет
подробно рассматриваться каждый оператор
файла ресурсов, сейчас же представим
их краткое описание.
Однострочные
операторы определяют растровые
изображения (BITMAP), курсоры (CURSOR), шрифты
(FONT), пиктограммы (ICON), язык ресурсов
(LANGUGE). Однострочный оператор состоит
из следующих частей:
Идентификатор
Тип_ресурса [Характеристика_загрузки]
Имя_файла_ресурса
-
Операторы BITMAP,
CURSOR, FONT и ICON также принимают дополнительные
параметры. Эти параметры указывают
характеристики загрузки и памяти для
ресурса. В 32-разрядной Windows используется
только один атрибут DISCARDABLE, указывающий,
что ресурс может быть удален из памяти,
если он больше не требуется, например:
MyBitmap
BITMAP DISCARDABLE “mybitmap.bmp”
-
Оператор LANGUGE
устанавливает язык всех последующих
ресурсов до конца сценария ресурсов
или до следующего оператора LANGUGE. Этот
оператор также можно использовать для
установки языка определенного ресурса
в многострочном операторе, если он
находится непосредственно перед
ключевым словом BEGIN в таком операторе.
После оператора LANGUAGE следуют идентификаторы
языка, которые должны быть константами,
определенными в файле winnls.h.
Многострочные
операторы в файле ресурсов определяют
диалоговые окна (DIALOG), таблицы строк
(STRINGTABLE), таблицы акселераторов
(ACCELERATORS), меню (MENU), пользовательские
данные (RCDATA) и ресурсы информации о
версии. Многострочные операторы
начинаются с идентификатора, оператора
и необязательных параметров, затем
следует блок инструкций, заключенный
между ключевыми словами BEGIN-END:
Идентификатор
ОПЕРАТОР [Необязательные_параметры]
[Необязательные_инструкции]
BEGIN
[Инструкции]
END
Необязательные_инструкции
могут включать, например, инструкцию
CAPTION, которая определяет заголовок
диалогового окна, или инструкцию STYLE
для установки стилей диалогового окна.
Пиктограммы
В приложение можно
добавить ресурс, который называется
пиктограмма (icon). Пиктограмма — это
графическое изображение небольшого
размера, состоящее из отдельных пикселов
(32×32).
Пиктограммы обычно
используют для обозначения свернутого
окна приложения, они отображаются в
левом верхнем углу заголовка окна
(размером 16х16, из “большого” изображения
исключается каждый второй столбец и
строка). С помощью редактора изображений
можно нарисовать свои пиктограммы и
использовать их в приложениях.
Приложения активно
работают с графическими изображениями,
состоящими из отдельных пикселов и
имеющих прямоугольную форму. Такие
изображения называются bitmap (битовый
образ). Можно считать, что пиктограмма
является упрощенным вариантом изображения
bitmap.
Пиктограммы хранятся
в файлах с расширением имени .ico. В одном
файле обычно находится несколько
вариантов пиктограмм. Когда Windows рисует
пиктограмму, она выбирает из файла
наиболее подходящую для текущего режима
работы видеоадаптера.
Для включения
пиктограммы в файл описания ресурсов
используется оператор ICON, ссылка на
файл пиктограммы выглядит примерно так
(в этом операторе пиктограмме присваивается
имя “MyIcon”):
MyIcon ICON iconfile.ico
В приложении для
получения дескриптора пиктограммы
используется функция LoadIcon:
HICON
LoadIcon(HINSTANCE hInst, LPCTSTR lpszIcon);
Первым параметром
является дескриптор экземпляра
приложения. Он необходим для того, чтобы
Windows могла определить, в каком файле
содержится ресурс пиктограммы. Вторым
параметром является имя пиктограммы
из описания ресурсов, заданное в виде
указателя на строку.
Если первый параметр
функции LoadIcon установлен в NULL, то Windows
узнает, что эта пиктограмма яляется
преодопределенной (с префиксом IDI_):
//загрузка
предопределенной пиктограммы
IDI_APPLICATION:
LoadIcon(NULL,IDI_APPLICATION);
Рассмотрим способы
загрузки пиктограмм, определенных в
ресурсах приложения
Имеется связь между
именем пиктограммы в описании ресурсов
и в вызове функции LoadIcon:
Описание
ресурсов: MyIcon ICON iconfile.ico
Текст
программы: HICON
hIcon=LoadIcon(hInst,”MyIcon”);
Вместо имени можно
также использовать число (16-разрядное
беззнаковое WORD) – это число называется
идентификатором пиктограммы. Тогда
связь между ссылкой на пиктограмму в
описании ресурсов и в вызове функции
LoadIcon имеет следующий вид:
Описание ресурсов: 125
ICON iconfile.ico
Текст программы: HICON
hIcon=LoadIcon(hInst,
MAKEINTRESOURCE(125));
MAKEINTRESOURCE является
макросом, определенным в заголовочных
файлах Windows, который преобразует число
в указатель, но со старшими разрядами,
установленными в нуль. Так Windows определяет,
что второй параметр функции LoadIcon является
числом, а не указателем на символьную
строку.
На имя пиктограммы
можно ссылаться и с помощью третьего
метода, который является комбинацией
первых двух методов (по символу #
операционная система определяет, что
далее следует число в ASCII-коде):
Описание ресурсов: 125
ICON iconfile.ico
Текст программы: HICON
hIcon=LoadIcon(hInst,”#125”);
Есть еще и четвертый
способ установки связи между ссылкой
на пиктограмму в описании ресурсов и в
вызове функции LoadIcon. В этом способе
используется макроопределение, которое
должно включаться и в файл описания
ресурсов, и в исходный текст программы:
Заголовочный
файл: #define MyIcon 125
Описание
ресурсов: MyIcon ICON iconfile.ico
Текст
программы: HICON
hIcon=LoadIcon(hInst,
MAKEINTRESOURCE(MyIcon));
Использование
идентификаторов вместо имен пиктограмм
уменьшает размер exe-файла, и вероятно,
немного ускоряет работу функции LoadIcon.
Дескриптор, выдаваемый
функцией LoadIcon, можно присвоить полю
пиктограммы структуры класса при
регистрании класса окна hWnd, тогда окно
hWnd будет иметь именно эту пиктограмму:
wndclass.hIcon=LoadIcon(hInst,”MyIcon”);
Для того, чтобы в
любой момент переопределить значение
поля пиктограммы в структуре класса
окна hWnd, следует воспользоваться вызовом:
SetClassLong(hWnd,GCL_HICON,LoadIcon(hInst,”AnotherIcon”));
После того, как
вы приложение загрузило пиктограмму,
ее можно также нарисовать в любом месте
экрана функцией DrawIcon.
Если загруженная с
помощью функции LoadIcon пиктограмма
приложению больше не нужна, то можно
освободить занимаемую ею память, вызвав
функцию DestroyIcon.
Курсоры
Приложение может
использовать не только стандартные
курсоры, но и альтернативные, хранящиеся
в ресурсах приложения. Курсор мыши
представляет собой не что иное, как
упрощенный вариант битового изображения,
аналогично пиктограмме
Инструкции для
задания курсора в файле описания ресурсов
и для получения его дескриптора в
программе очень похожи на аналогичные
инструкции для пиктограмм:
Описание
ресурсов: MyCursor CURSOR cursfile.cur
Текст
программы: HCURSOR
hCursor=LoadCursor(hInst,”MyCursor”);
Другие способы,
показанные для пиктограмм (использование
идентификаторов и MAKEINTRESOURCE), также
работают и для курсоров.
Дескриптор курсора
мыши, полученный при вызове функции
LoadCursor, можно использовать при задании
поля курсора структуры класса при
регистрании класса окна. Это заставляет
курсор мыши, если он оказывается в
рабочей области окна, превращаться в
пользовательский курсор:
wndclass.hCursor=
LoadCursor(hInst,»MyCursor”);
Изменить курсор для
окна можно в любое другое время,
переопределив значение, содержащееся
в структуре класса окна:
SetClassLong(hWnd,GCL_HCURSOR,LoadCursor(hInst,”AnotherCursor”));
Для динамического
изменения формы курсора следует
использовать функцию SetCursor, используя
в качестве параметра дескриптор нового
курсора, подготовленный при помощи
функции LoadCursor.
Функцию SetCursor следует
вызывать при обработке сообщения
WM_MOUSEMOVE. В противном случае для перерисовки
курсора при его движении Windows использует
курсор, ранее заданный в классе окна.
Для того чтобы
выключить изображение курсора или вновь
его включить, используют функцию
ShowCursor.
Операционная оболочка
Windows содержит несколько встроенных
курсоров. Их идентификаторы описаны в
файле windows.h и начинаются с префикса
IDC_. Для загрузки встроенных курсоров
также используется функция LoadCursor, но в
качестве первого параметра ей передается
NULL:
LoadCursor(NULL,IDC_ARROW);
Если курсор,
загруженный с помощью функции LoadCursor,
приложению больше не нужен, то можно
освободить занимаемую им память, вызвав
функцию DestroyCursor.
Битовые изображения
В ресурсы приложения
можно включать произвольные графические
изображения в виде битового образа
(изображение типа bitmap). С помощью
графических редакторов можно нарисовать
графическое изображение типа bitmap.
Изображение записывается в файл с
расширением имени .bmp.
Изображения bitmap
удобно использовать для внешнего вида
окон приложения, они открывают широкие
возможности для разработки дизайна
приложения Windows.
Битовый образ
включается в файл описания ресурсов в
том же формате, что значок или курсор:
MyBmp BITMAP bmpfile.bmp
Для загрузки ресурса
используется функция LoadBitmap. Ее возвращаемым
значение является дескриптор битового
образа:
HBITMAP
hBitmap=LoadBitmap(hInst,”MyBmp”);
Другие способы,
показанные для пиктограмм (использование
идентификаторов и MAKEINTRESOURCE), также
работают и для битовых изображений.
Битовые образы
используются в двух главных целях.
-
Первая – рисование
на экране картинок: битовые образы
можно просто рисовать в рабочей области
окна; можно использовать их в кнопках,
определяемых пользователем; применять
при работе с меню, пункты которого
отрисовываются пользователем. -
Вторая цель
использования битовых образов –
создание кистей. Кисти являются шаблонами
пикселей, которые Windows использует для
закрашивания изображаемых на экране
областей.
Одно из простых
применений изображений bitmap — раскрашивание
фона окна. После загрузки изображения
функцией LoadBitmap приложение должно создать
из этого изображения кисть, вызвав
функцию CreatePatternBrush. Функция CreatePatternBrush
возвращает идентификатор кисти, который
можно использовать при регистрации
окна (перед завершением работы приложения
созданная кисть должна быть уничтожена
функцией DeleteObject):
HBRUSH
hBrush=CreatePatternBrush(hBitmap);
wndclass.hbrBackground=hBrush;
Когда Windows раскрашивает
этой кистью область экрана, битовый
образ повторяется по горизонтали и
вертикали через каждые восемь пикселей.
После загрузки
растрового изображения его можно также
использовать для вывода в рабочую
область окна. Рассмотрим пример вывода
битового изображения при ответе на
сообщение WM_PAINT.В приводимом примере
размер выводимого битового изображения
60х60 пикселя; выводится оно, начиная от
точки с координатами (100, 100):
PAINTSTRUCT
ps;
HDC hDC=BeginPaint(hWnd,&ps);
HDC
BitmapDC=CreateCompatibleDC(hDC);
HBITMAP
hOldBitmap=SelectBitmap(BitmapDC,hBitmap);
BitBlt(hDC,100,100,60,60,BitmapDC,0,0,SRCCOPY);
SelectBitmap(BitmapDC,hOldBitmap);
DeleteDC(BitmapDC);
EndPaint(hWnd,&ps);
Этот код создает
еще один контекст устройства, совместимый
с контекстом устройства окна. Это
делается при помощи функции
CreateCompatibleDC. Прежде чем растровое
изображение сможет быть выведено на
экран, оно сначала должно быть выбрано
в этот второй контекст устройства.
Функция SelectObject
выбирает объект в данный контекст
устройства. Она всегда возвращает
объект, который перед этим был в контексте
устройства (для последующего
восстановления). После того, как растровое
изображение показано и восстановлено
предыдущее растровое изображение, нужно
удалить второй контекст устройства при
помощи DeleteDC.
Главное отличие
между битовыми образами и остальными
ресурсами в их практической важности
и может быть легко выражено так: битовые
образы являются объектами GDI.
Хороший стиль
составления программ рекомендует, что
битовые образы, созданные функцией
LoadBitmap, должны быть удалены при помощи
функции DeleteObject, как только в них пропадает
необходимость или если программа
завершается.
Символьные строки
Наличие ресурса для
символьных строк сначала может показаться
странным. Тем более, что нет никаких
проблем в использовании привычных
символьных строк, определенных в качестве
переменных непосредственно в теле
исходного текста приложения.
Ресурсы символьных
строк предназначены главным образом
для облегчения перевода приложения на
другие языки.
Ресурс таблицы строк
определяет произвольное количество
текстовых строк. Приложения ссылаются
на эти строки по символьным идентификаторам.
Основное преимущество
использования таблицы строк – размещение
всех зависимых от языка компонентов в
файле ресурсов, что существенно упрощает
задачу локализации приложения.
Таблица строк
определяется ключевым словом STRINGTABLE,
за которым указаны необязательные
инструкции и одно или более определений
строк, заключенных между ключевыми
словами BEGIN-END:
STRINGTABLE
BEGIN
id1 “character string 1”
id2
“character string
2”
// определения
остальных строк
END
Идентификаторы
строк, которые предшествуют каждой
строке, должны быть или числами, или
идентификаторами макроопределений,
которые задаются в заголовочном файле.
В описании ресурсов может быть только
одна таблица строк. Максимальный размер
каждой строки – 255 символов.
Например:
STRINGTABLE
BEGIN
IDS_HELLO “Hello”
IDS_BYE
“Good bye”
END
Здесь IDS_HELLO и IDS_BYE –
символьные идентификаторы, определенные
в другом месте, например, так:
# define
IDS_HELLO 1
#define
IDS_BYE 2
Для копирования
строки из ресурсов приложения в буфер
в сегменте данных приложения, следует
использовать функцию LoadString, затем этот
буфер можно использовать как обычную
строку:
char szBuffer[256];
LoadString(hInst,id,szBuffer,iMaxLength);
MessageBox(hWnd, szBuffer,”Text
from stringtable”,MB_OK);
-
Параметр id
соответствует идентификатору, который
предшествует каждой строке в файле
описания ресурсов; iMaxLength – максимальное
число передаваемых в szBuffer символов.
Ресурсы, определяемые
пользователем
Синтаксис файла
ресурсов позволяет создавать также
пользовательские типы ресурсов.
Ресурсы, определяемые
пользователем (user-defined resource) удобны для
включения самых разнообразных данных
в загрузочный файл и для получения
доступа в приложении к этим данным.
Данные могут содержаться в любом формате
– текстовом или бинарном.
При загрузке данных
в оперативную память возвращаемым
значением функций Windows, которые
используются для доступа к определяемым
пользователем ресурсам, является
указатель на данные. С этими данными
можно делать все, что угодно приложению.
Операторы для
пользовательских ресурсов могут быть
как однострочными, так и многострочными.
Процесс использования
многострочных операторов для включения
пользовательских ресурсов
Однострочные
операторы используются для указания
пользовательских ресурсов, которые
хранятся в отдельных файлах. Вот как,
например, в файле ресурсов приложения
описывается ссылка на файл с данными:
MyData TEXT filedata.dat
Имена MyData (имя
ресурса) и TEXT (тип ресурса) в операторе
могут быть любыми. В данном примере был
создан ресурс собственного типа, который
называется TEXT. Для того, чтобы получить
дескриптор ресурса, необходимо вызвать
функцию LoadResource:
HGLOBAL
hResource=LoadResource(hInst,FindResource(hInst,”TEXT”,”MyData”));
Вместо имен и типов
в описании пользовательского ресурса
можно использовать числа. Числа могут
быть преобразованы в указатели при
вызове функции FindResource с использованием
MAKEINTRESOURCE. Числа, используемые в качестве
типа ресурса, должны быть больше 255
(меньшие числа использует Windows).
Несмотря на свое
имя, функция LoadResource фактически не
загружает ресурс сразу в оперативную
память. Когда к ресурсу необходимо
получить доступ, следует вызвать функцию
LockResource, используя оператор такого типа:
ТИП
*ptr=(ТИП
*)LockResource(hResource);
Функция LockResource
загружает ресурс в память (если он еще
не был загружен), и возвращает указатель
на него.
После окончания
работы с этим ресурсом приложение может
освободить оперативную память, вызвав
функцию FreeResource:
FreeResource(hResource);
Процесс использования
многострочных операторов для включения
пользовательских ресурсов.
Многострочные
операторы для пользовательских ресурсов
используются для внедрения определений
пользовательских ресурсов в файл
ресурсов. Синтаксис многострочных
операторов пользовательских ресурсов:
имя тип [опции]
BEGIN
неструктурированные_данные
END
Блок
неструктурированные_данные может
содержать целые значение в десятичном,
шестнадцатеричном или восьмеричном
представлении или строки, заключенные
в двойные кавычки. Строки неструктурированных
данных должны явно завершаться нулем.
Отдельные пункты данных разделяются
запятыми.
Неструктурированные
данные также можно определить в форме
ресурса RCDATA. Синтаксис RCDATA и синтаксис
многострочного оператора почти идентичны,
но в случае оператора неструктурированных
данных вместо типа используется ключевое
слово RCDATA, а также этот оператор может
содержать необязательные операторы
CHARACTERISTICS, LANGAGE и VERSION.
Например:
resname RCDATA
BEGIN
“Here is
an ANSI string”, // строка,
ограниченная нулем
*/
L“Here is a
Unicode string”, // строка
UNICODE, ограниченная нулем
1024, //
целое, хранящееся
WORD
7L, //
целое, хранящееся
DWORD
0x029a,
// шестнадцатеричное целое
0733, // восьмеричное
END
Характерной особенностью исполняемых модулей и динамических библиотек Windows является наличие в них так называемых ресурсов. Иконки, курсоры, диалоговые окна, меню, графические образы и текстовые таблицы, а так же информация о версии файла являются неотъемлемой частью большинства приложений с графическим интерфейсом для Windows. Как известно, исполняемый модуль состоит из заголовка файла PE-формата (Portable Executable) и нескольких секций, одна из которых является секцией ресурсов.
В системных библиотеках Windows API имеется набор функций для работы с ресурсами. Вначале я расскажу в этой статье о функциях поиска ресурсов в модулях Windows, а потом о функциях загрузки данных из ресурсов.
Если имя и тип ресурса в указанном модуле заранее известны, то этот ресурс можно найти с помощью функции FindResource или FindResourceEx. Если содержимое ресурсной части модуля заранее неизвестно, то можно получить список имеющихся в модуле ресурсов с помощью функций EnumResourceTypes и EnumResourceNames.
Ресурсы приложения могут быть локализованы под разные национальные языки. Для перечисления имеющихся в ресурсах локализаций применяется функция EnumResourceLanguages.
Для отдельных типов ресурсов предусмотрены специальные функции загрузки.
- LoadString – загрузка текстовой строки,
- LoadBitmap – загрузка растрового изображения,
- LoadCursor – загрузка графического образа курсора мыши,
- LoadIcon – загрузка образа пиктограммы (иконки),
- LoadMenu – загрузка ресурса меню,
- LoadAccelerators – загрузка таблицы «быстрых клавиш»,
- LoadResource – загрузка прочих ресурсов.
Существует много программ, которые позволяют просматривать ресурсы в бинарных модулях и даже редактировать их. Редактор ресурсов, имеющийся в составе Visual C++, способен редактировать ресурсы как в исходных файлах проекта, так и внутри бинарных модулей. При этом можно экспортировать ресурсы из бинарного модуля в отдельные файлы на диск.
Я предлагаю познакомиться с небольшой программой моей собственной разработки, которая позволяет извлекать ресурсы из модулей Windows-приложений и динамических библиотек. Выглядит она так:
Эта программа извлекает ресурсы из бинарного модуля и сохраняет их на диске в виде отдельных файлов.
С помощью кнопки «Файл» программа через стандартный диалог Windows для выбора файлов загружает указанный бинарный модуль, чтобы получить список его ресурсов.
В списке ресурсов модуля указывается тип каждого ресурса, идентификатор ресурса и размер его данных.
При нажатии кнопки «Экспорт» создаётся отдельный каталог на диске, в который записываются файлы с данными соответствующих ресурсов.
Кроме этого программа позволяет посмотреть список имеющихся в модуле иконок. Это делается с помощью кнопки «Иконки» и стандартного диалога Windows для выбора значка.
Так же можно узнать информацию о текущей версии файла. Кнопка «Версия» вызывает окно диалога с
данными о текущей версии модуля.
Загрузить приложение: GrabRes.zip [ZIP;60Кб]
Ресурсы являются составной частью приложения для Windows. В них определяются такие объекты, как пиктограммы, курсоры, меню, диалоговые окна и другие. Часть объектов используемых ресурсов могут быть стандартными и системе достаточно дать указание на их использование.
Все нестандартные объекты ресурсов должны быть описаны вASCII- файле с расширением.rcна специальном языке описания объектов ресурсов. Теоритически этот файл может быть написан в обычном текстовом редакторе, но обычно в любой среде имеются графические редакторы, позволяющие упростить и автоматизировать процесс написания файла ресурсов с любыми объектами.
В составе MicrosoftVisualStudio 2008 имеется следующий набор редакторов ресурсов:
- Редактор меню;
- Редактор диалоговых окон;
- Редактор панелей инструментов;
- и другие редакторы.
Каждый из указанных редакторов изучается в процессе применения того или иного объекта ресурсов в Windows –приложении.
Меню является важным элементом Windows – приложения. Практически в каждом приложении отображается полоса меню (menubar), содержащая набор пунктов. Пункт меню обозначается своим именем – словом или фразой.
Меню, располагающееся под заголовком приложения, называется главным меню (mainmenu), или меню верхнего уровня.
Различают два типа пункта меню:
- пункт – подменю;
- пункт – команда.
Пункт – подменю – это имя вызываемого меню следующего более низкого уровня иерархии. Если пользователь в меню щелчком левой кнопки мыши выбрал пункт подменю, то Windows выводит на экран прямоугольник этого подменю, называемого всплывающим меню (popupmenu). Пункты подменю размещаются в виде вертикального столбца, при навигации по подменю выделяются цветовой инверсией. Пункты подменю могут быть объединены в логические группы.
Пункт – команда — это конечный пункт на иерархическом дереве меню. Выбор его должен изменить внутреннее состояние приложения, либо привести к некоторому действию. Реакция Windows на выбор этого пункта меню – отправка приложению сообщения WM_COMMAND, содержащего идентификатор этой команды.
Пункт – подменю – это заголовок вызываемого меню следующего, более низкого уровня. Пункты меню могут быть разрешенными (enabled), запрещенными (disabled), недоступными (grayed).
По умолчанию пункт меню является разрешенным. Когда пользователь выбирает его, система отображает соответствующий пункт подменю или посылает сообщение WM_COMMAND.
Запрещенные (disabled)и недоступные (grayed)пункты с точки зрения их поведения одинаковы. Их можно выделить, но нельзя выбрать (ничего не происходит при их выделении). Отличаются запрещенный пункт и недоступный только внешним видом – недоступный отображается серым цветом, что очень наглядно. Если необходимо, чтобы пользователь знал, что пункт «отменен», его следует назначить недоступным.
Меню создается на основе шаблона меню, определенного в файле описания ресурсов .rc
Определение меню в файле ресурсов имеет следующий вид:
имя_менюMENUDISCARDABLE
BEGIN
Описание 0-го пункта
Описание 1-го пункта
……………….
Описание (n-1)-го пункта
END
Синтаксис описания i-того пункта меню зависит от типа пункта.
Описание шаблона пункта – подменю имеет следующий вид:
POPUPимя_пункта[, параметры]
BEGIN
Описание 0-го пункта
Описание 1-го пункта
……………….
Описание (n-1)-го пункта
END
Описание пункта – команды имеет следующий вид:
MENUITEMимя_пункта идентификатор [, параметры]
Если вместо имени пункта меню использовано слово SEPARATOR, это приведет к тому, что вместо меню будет отображена горизонтальная разделительная линия
Шаблон меню создается автоматически при использовании редактора меню.
Таблица 1. Некоторые часто используемые типы Win32
Тип данных | Описание |
BOOL | Булевский тип (эквивалент bool ) |
BYTE | Байт (8-битное целое без знака) |
DWORD | 32-битное целое без знака |
HANDL | Дескриптор объекта |
HGDIOBJ | Дескриптор графического объекта |
HBITMAP | Дескриптор растрового изображения |
HBRUSH | Дескриптор кисти |
HCURSOR | Дескриптор курсора |
HDC | Дескриптор контекста устройства |
HFONT | Дескриптор шрифта |
HICON | Дескриптор иконки (пиктограммы) |
HINSTANCE | Дескриптор экземпляра приложения |
HMENU | Дескриптор меню |
HPEN | Дескриптор пера |
HWND | Дескриптор окна |
INT | 32-битное целое со знаком |
LONG | 32-битное целое со знаком |
LPARAM | Тип, используемый для описания lParam, четвертого параметра оконной процедуры |
LPCSTR | Указатель на константную С-строку |
LPCWSTR | Указатель на константнуюUnicode-строку (строка также заканчивается символом, имеющим код 0), но на для хранения одного символа используется два байта. Чтобы использовать в проекте кодировку UNICODE , надо предусмотреть в проекте директиву #defineUNICODE |
LPCTSTR | LPCWSTR,если определен макрос UNICODE, и LPCSTRв противном случае |
LPSTR | Указатель С-строку |
LPWSTR | Указатель на Unicode-строку |
LPTSTR | LPWSTR,если определен макрос UNICODE, и LPSTRв противном случае |
LRESULT | Значение типа LONG, возвращаемое оконной процедурой |
NULL | ((void*) 0) |
TCHAR | wchar_t (Unicode-символ), если определен макрос UNICODE, и charв противном случае |
UINT | 32-битное целое без знака |
WPARAM | Тип, используемый для описания wParam, третьеого параметра оконной процедуры |
Вызов редактора меню
Если вы создавали не пустой проект Win32 Project, то в нем уже создано минимальное меню по умолчанию. Его модификацию делаю в Редакторе ресурсов. Попасть в Редактор ресурсов можно, открыв в меню ВидподменюРесурсы, или в Обозревателе решений открыть файл с расширением .rc, дважды щелкнув по его имени.
Файл с расширением .rc, который является текстовым файлом, можно открыть и в текстовом редакторе, для этого нужно вызвать всплывающее меню нажатием правой кнопки мыши, открыв его в подменюОткрыть с помощью…
Если дважды щелкнуть по пункту меню, то будет отображено диалоговое окно Свойства (Properties).
Назначение наиболее употребительных атрибутов окна Свойствпоказано в табл.
Атрибут | Описание |
Включен | Показывает, что пункт меню может быть выбран |
Всплывающее меню(Pop-up) | Пункт определяет подменю, если флажок отмеченtrue. В противном случае пункт является обычной командой |
Надпись(Caption) | Имя пункта (если в имени встречается символ “”, то следующий за ним символ является мнемоническим) |
Неактивный (Grayed) | Пункт меню неактивен(недоступен в исходном состоянии), его текст выводится серым цветом (несовместим с атрибутом Inactive) |
Установлен(Checked) | При выводе на экран пункт помечается слева галочкой |
Разрыв(Break) | Этот атрибут может принимать одно из трех значений:· None (нет)– обычный пункт меню;· Column — для меню верхнего уровня пункт выводится с новой строки, а для подменю – в новом столбце;Bar — дополнительный столбец подменю отделяется вертикальной линией |
ID | Идентификатор пункта – доступен для команд |
Разделитель(Separator) | Пункт представляет собой горизонтальную разделительную линию |
Статьи к прочтению:
- Rexec (remote execution) — выполнение одной команды на удаленной unix-машине.
- Режимы отображение палитры character
Как удалить встроенные в Windows 10, ненужные и пожирающие ресурсы ПК приложения
Похожие статьи:
-
Удаление приложений windows
Удаление ранее установленных приложений Windows производится средствами того же диалогового окна Свойства: Установка и удаление программ. Следует…
-
Операционная система windows 1. графический интерфейс
Операционная система Программное обеспечение ЭВМ можно разделить на 3 части: системное ПО, прикладное ПО и системы программирования. Системное ПО -…
Ресурсы приложения Windows – это данные, которые встроены внутрь EXE, DLL, CPL и MUI файлов. Общеизвестным примером такого ресурса является иконка приложения. Windows API предопределяет большое количество типов ресурсов приложений. Кроме них приложения могут определять свои собственные типы ресурсов. Хотя, как я понимаю, они все будут равнозначны RCDATA. Давайте добавим приложению как ресурсы логотип и пользовательское соглашение, а при его старте загрузим их на форму.
Добавление ресурсов в приложение начинается с создания текстового файла, который их описывает:
License TEXT «license.txt»
123 RCDATA «BlackCat.jpg»
Назовем его «AddRes.rc». «RC» – это стандартное расширение для таких файлов. В файле описаны два ресурса. Первый называется «License», имеет нестандартный тип «TEXT» и ссылается на текстовый файл «license.txt». Второй имеет целочисленный идентификатор «123», предопределенный тип «RCDATA» и ссылается на файл JPEG-формата «BlackCat.jpg».
Теперь нам нужно скомпилировать наш RC-файл. Для этого у RAD Studio есть три компилятора командной строки:
- Borland Resource Compiler (BRCC32.EXE):
- Microsoft SDK Resource Compiler (RC.EXE).
- CodeGear Resource Compiler/Binder (CGRC.EXE).
В реальности CGRC.EXE – это не компилятор. Это программа, которая переводит параметры BRCC32.EXE в параметры RC.EXE и запускает с ними RC.EXE.
Все три варианта создадут нам файл с расширением «RES», который нам нужно включить в проект с помощью директивы «$R»:
program GetResource; uses Vcl.Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} {$R AddRes.res} begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.Run; end.
Но есть более простой и надежный способ – это добавить RC-файл в проект:
program GetResource; uses Vcl.Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.res} {$R 'AddRes.res' 'AddRes.rc'} begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.Run; end.
В этом случае нам не нужно вызывать компилятор ресурсов каждый раз при их изменении, а достаточно просто перекомпилировать проект. В параметрах проекта можно выбрать, какой из компиляторов RAD Studio будет использовать для этого (BRCC32.EXE или CGRC.EXE/RC.EXE):
Доступ к ресурсам приложения можно получить через функции Windows API. Мы же воспользуемся реализованным в Delphi специальным потоком для чтения ресурсов приложения – TResourceStream. Он позволяет получить доступ к ресурсам по имени (ResName):
constructor TResourceStream.Create(Instance: THandle; const ResName: string; ResType: PChar);
или по целочисленному идентификатору (ResID):
constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer; ResType: PChar);
Параметры:
- Instance – это дескриптор приложения или DLL содержащие ресурс.
- ResType – это строка, определяющая тип ресурса. Предопределенные типы в Delphi описаны в модуле WinApi.Windows.
Создадим в Delphi новый VCL-проект. Добавим на форму два контрола «imgLogo: TImage» — для загрузки изображения и «mLicense: TMemo» — для загрузки текста. В событие FormCreate добавим загрузку ресурсов на форму:
unit Unit1; interface uses System.Classes, System.SysUtils, System.Types, Winapi.Windows, Vcl.Forms, Vcl.Graphics, Vcl.Controls, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.Imaging.jpeg; type TForm1 = class(TForm) imgLogo: TImage; mLicense: TMemo; procedure FormCreate(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); var rs: TResourceStream; begin // загрузка по целочисленному идентификатору rs := TResourceStream.CreateFromID(HInstance, 123, RT_RCDATA); try var jpg: TJPEGImage := TJPEGImage.Create; try jpg.LoadFromStream(rs); imgLogo.Picture.Assign(jpg); finally jpg.Free end; finally rs.Free end; // загрузка по имени rs := TResourceStream.Create(HInstance, 'License', 'TEXT'); try var ss: TStringStream := TStringStream.Create; try ss.LoadFromStream(rs); mLicense.Text := ss.DataString; finally ss.Free; end; finally rs.Free end; // загрузка не существующего ресурса rs := TResourceStream.Create(HInstance, 'freedom', RT_ICON); try finally rs.Free end; end.
При запуске приложения мы получим сообщение об ошибке:
Оно информирует, нас о том, что ресурс «freedom» не найден. С этим легко можно столкнуться, если загружать ресурсы из другого модуля неправильной версии. Что бы избежать подобной досадной неожиданности можно проверить наличие ресурса с помощью функции FindResource:
if FindResource(hInstance, 'freedom', RT_ICON) <> 0 then begin rs := TResourceStream.Create(HInstance, 'freedom', RT_ICON); try finally rs.Free end; end;
или заключить загрузку ресурса в try-except (это дополнительно поможет избежать ошибки при не правильном формате ресурса):
try rs := TResourceStream.Create(HInstance, 'freedom', RT_ICON); try finally rs.Free end; except end;
Примечание. К ресурсу с целочисленным идентификатором тоже можно обратиться по имени. Для этого перед его идентификатором нужно поставить символ «#»:
if FindResource(hInstance, '#123', RT_RCDATA) <> 0 then begin rs := TResourceStream.Create(HInstance, '#123', RT_RCDATA);