Дата публикации статьи: 01.12.2005 15:54

Исходный код к статье

Ресурсы в исполняемом файле могут быть разными – иконки, курсоры, таблицы строк, таблицы акселераторов, диалоги, растры, описание версии и т.д. Каждый ресурс относится к какому-то типу, выражаемому целым числом типа integer.

Перечислить типы ресурсов в файле можно при помощи функции EnumResourceTypes. Каждый ресурс имеет уникальное для данного файла имя. Имена всех ресурсов данного типа, используемые в файле, можно перечислить функцией EnumResourceNames.

Описать работу со ВСЕМИ типами ресурсов в небольшой статье невозможно, ведь к каждому ресурсу нужно подходить инливидуально, поэтому разберемся с наиболее сложным (и плохо документированным) случаем – иконки и их группы. Для начала создайте проект Standart в Basic 6. В него добавьте модуль и назовите, например, GlobalMdl.bas – перечень всех используемых ф-ий, констант и типов будем держать здесь. В нем потребуются следующие объявления (не все эти ф-ии и константы можно найти в АПИВьюере):

Option Explicit
'Константы, определяющие тип ресурсов
Public Const RT_GROUP_ICON = 14&
Public Const RT_ICON = 3&
'Функция, удаляющая иконку из памяти
Public Declare Function DestroyIcon Lib "user32" (ByVal hIcon As _
Long) As Long
'Функция, рисующая иконку
Public Declare Function DrawIcon Lib "user32" (ByVal HDC As Long, _
ByVal x As Long, ByVal y As Long, ByVal hIcon As Long) As Long
'Находит ресурс по идентификатору
Public Declare Function FindResource Lib "kernel32" Alias "FindResourceA" (ByVal hInstance As Long, ByVal lpName As _
String, ByVal lpType As String) As Long
'Загружает ресурс по ссылке из FindResource
Public Declare Function LoadResource Lib "kernel32" (ByVal _
hInstance As Long, ByVal hResInfo As Long) As Long
'Фиксирует ресурс и дает адрес его первого байта
Public Declare Function LockResource Lib "kernel32" (ByVal _
hResData As Long) As Long
'Грузит файл в оперативную память
Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
'Удаляет файл из оперативной памяти по ссылке, данной LoadLibrary
Public Declare Function FreeLibrary Lib "kernel32" (ByVal _
hLibModule As Long) As Long
'Освобождает из памяти ресурс
Public Declare Function FreeResource Lib "kernel32" (ByVal _
hResData As Long) As Long
'Функция, перечисляющая идентификаторы (имена) ресурсов
Public Declare Function EnumResourceNames Lib "kernel32" Alias "EnumResourceNamesA" (ByVal hModule As Long, _
ByVal lpType As String, ByVal lpEnumFunc As Long, ByVal _
lParam As Long) As Long
'Функция, создающая ссылку на иконку по первому ее байту
'Эта функция немного видоизменена - первый параметр в АПИВьюере дается типа BYTE, однако т.к. в барсике нет указателей
'мы его сделали лонг, но никто ругаться не будет!
Public Declare Function CreateIconFromResource Lib "user32" _
(ByVal presbits As Long, ByVal dwResSize As Long, ByVal fIcon _
As Long, ByVal dwVer As Long) As Long
'Функция, дающая размер ресурса по указатели, полученному от FindResource
Public Declare Function SizeofResource Lib "kernel32" _
(ByVal hInstance As Long, ByVal hResInfo As Long) As Long
'Функции из спец библиотеки
'Выдает кол-во иконок в группе
Public Declare Function IcoCNT Lib "reshack.dll" Alias "_WriteStructIco@12" (ByRef iconame As Integer, _
ByRef icocount As Long, ByVal mdlnam As String) As Long
'Выдает ссылку на иконку по идентификатору группы и порядковому номеру иконки в группе
Public Declare Function IcoHandle Lib "reshack.dll" Alias "_GetIconHandle@12" (ByRef iconame As Integer, _
ByVal libname As String, ByRef iconumber As Long) As Long
Public LibHandle As Long   'Ссылка на загружаемый файл
'ф-ия по полному пути извлекает имя файла
Public Function GetFileN(FileN As String) As String
    GetFileN = Mid(FileN, InStrRev(FileN, "\") + 1, Len(FileN) - 1 - InStrRev(FileN, "\") + 1)
End Function
'Callback функция для перечисления имен ресурсов
Public Function ResCallbackNames(ByVal hModule&, ByVal lpType&, ByVal lpName&, ByVal lParam&) As Long
    'Если нам передали нолик, то заполняем List1, иначе - List2
    If lParam = 0 Then
        IcoMainfrm.List1.AddItem Str(lpName)
        ResCallbackNames = 1
    Else
        IcoMainfrm.List2.AddItem Str(lpName)
        ResCallbackNames = 1
    End If
End Function

Теперь пробегусь по всем ф-иям (В МСДН они описаны не совсем точно и понятно):
Константы:
RT_ICON = 3  - тип ресурса «иконка»
RT_GROUP_ICON = 14 – тип ресурса «группа иконок»

DestroyIcon – уничтожает иконку (освобождает отведенную ей память)
 Hicon as long – ссылка на иконку.
 Возвращает 0 в случае неудачи, другое целое – в случае успеха
DrawIcon – рисует иконку
 HDC as long – контекст устройства, в котором будем рисовать
 X as long – смещение по горизонтали от левого верзнего угла устройства
 Y as long – смещение по вертикали от левого верхнего угла устройства
 Hicon as long – ссылка на иконку
 Возвращает 0 в случае неудачи, другое целое – в случае успеха
FindResource – находит ресурс в загруженном в память файле по имени и типу
 hInstance as long – ссылка на файл, загруженный в память
 lpName as string – имя ресурса в виде “#” & имя_ресурса & chr(0)
 lpType as string – тип ресурса, построенный по тому же принципу
Возвращает 0 в случае неудачи, ЛОКАЛЬНУЮ ссылку НА РЕСУРС в файле
LoadResource – загружает ресурс
 hInstance as long – ссылка на файл, загруженный в память
 hResInfo as long – то, что вернула FindResource
Возвращает 0 в случае неудачи, ГЛОБАЛЬНУЮ ссылку НА РЕСУРС в файле
LockResource – фиксация ресурса
 hResData as long – то, что вернула LoadResource
Возвращает 0 в случае неудачи, адрес 1-го байти памяти, где располагается загруженный ресурс
LoadLibrary – чтобы работать с ресурсами файла мы должны загрузить этот файл (по-умному – спроецировать в адресное пространство нашего процесса). Этой функции мы должны передать полный путь к файлу, а она вернет нам ссылку на этот файл в памяти, или 0 в случае неудачи. Ссылка, которую возвращает эта ф-ия – это и есть параметр hInstance, который требуют функции выше (и ниже)
FreeLibrary – удаляет из памяти згруженный функцией LoadLibrary файл. Этой функции мы должны передать ссылку, полученную от LoadLibrary.
FreeResource – освобождает ресурс, загруженный функцией LoadResource
 hResData as long – то, что вернула LoadResource
EnumResourceNames – перечисляет имена ресурсов определенного типа
 hModule as long – то, что вернула LoadLibrary
 lpType as string - тип ресурса в виде “#” & тип_ресурса & chr(0)
 lpEnumFunc as long – адрес callback функции, определенной специальным образом
 lParam as long – параметр, который будет передан callback функции
callback функция определяется так:
Public Function ResCallbackNames(ByVal hModule&, ByVal lpType&, ByVal lpName&, ByVal lParam&) As Long
hModule – hModule функции EnumResourceNames
lpType – lpType функции EnumResourceNames
lpName – имя ресурса, полученное в результате работы функции
lParam – параметр, который мы передали
Если callback функция возвращает 0, то перечисление прекращается, иначе – продолжается до последнего ресурса данного типа.
CreateIconFromResource – по данным параметрам создает иконку и дает нам (наконец-то!) ссылку НА ИКОНКУ
 Presbits as long – то, что вернула функция LockResource
 dwResSize as long – Размер ресурса
 fIcon as long – 1 если загружается иконка, 0 – если курсор
 dwVer – версия иконки. Начиная с windows 3.11 мы пишем H30000
В случае неудачи возвращает 0, иначе – ССЫЛКУ НА ИКОНКУ
SizeOfResource – возвращает РАЗМЕР ресурса
 hInstance as long – то, что возвращает LoadLibrary
 hResInfo as long – то, что возвращает FindResource
Возвращает 0 в случае неудачи, иначе – размер ресурса в байтах
IcoCNT – возвращает кол-во иконок в ГРУППЕ ИКОНОК
 Iconame as ibteger – имя ресурса ГРУППЫ ИКОНОК
 Icocount as integer – буфер, куда будет записано кол-во иконок
 Mdlnam as string – имя загруженного в память файла, с котрым идет работа. Мы получаем это имя небольшой собственной функцией GetFileN, которая из пути к файлу выделяет его имя
 IcoHandle – возвращает ССЫЛКУ НА ИКОНКУ, по имени группы иконок и порядковому номеру иконки в группе.
 Iconame as integer – имя группы иконок
 Libname as string – то же, что и mdlname
 Iconumber as long – порядковый номер иконки
Возвращает 0 в случае неудаче, иначе – ссылку на иконку… ну и вылететь может… наверное.
Код формы – в примере, там же откомпиленная библиотека.
Код библиотеки тоже там. Он основан на том, что когда мы делаем LockResource для ГРУППЫ ИКОНОК, результат – ссылка на байт в памяти – указывает на структуру

typedef struct
{
    WORD           idReserved;   // всегда 0
    WORD           idType;       // для иконок 1
    WORD           idCount;      // сколько иконок в группе
    ICONDIRENTRY[idCount]
} ICONDIR, *LPICONDIR;
Последний параметр
typedef struct
{
    BYTE        bWidth;          // ширина иконки
    BYTE        bHeight;         // высота иконки
    BYTE        bColorCount;     // число цветов в изображении
    BYTE        bReserved;       // 0
    WORD        wPlanes;         // Color Planes – не понял, че такое
    WORD        wBitCount;       // бит на пиксель
    DWORD       dwBytesInRes;    // размер в байтах
    WORD        nID;   // идентификатор иконки – читай,
// имя иконки, которое после
// преобразований можно юзать в
// FindResource
} ICONDIRENTRY, *LPICONDIRENTRY;

Естественное (и пока непреодоленное) ограничение – это ограничение макроса MAKEINTRESOURCE – который преобразует имя и тип ресурса в приемлемую для функций строку.

Автор: kergank@gmail.com