Помещение файла в ресурсы и извлечение его из ресурсов

ОГЛАВЛЕНИЕ

Один из способов - это добавить в файл описания ресурсов (*.rc) строку
ResurceName ТИП_РЕСУРСА "Имя файла"

где:
ResurceName - уникальное имя ресурса. Будем им пользоваться при загрузке ресурса. В принципе здесь может стоять и числовой индентификатор ресурса (можно и определенный через #define, но тогда необходимо, чтобы из того места кода, где мы будем грузить ресурс, это определение тоже было видно; в таком случае обычно эти определения выносятся в заголовочный файл ресурсов- для них (файлов) принято использовать расширение *.rh).
ТИП_РЕСУРСА - идентификатор типа ресурса. RCDATA - специальный тип для бинарных ресурсов (грубо говоря, массив байт лежит как есть). *.wav тоже можно объявить как RCDATA, но принято его "регистрировать" как WAVE.
"Имя файла" - полное имя подключаемого файла вместе с расширением (директории разделяются одиночным '\').

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


 

Извлечение файла из ресурсов 

Достают конечно же не сам файл, а массив байт, который этот файл представляет. Т.е. получают указатель на начало этого массива:

    //Получаем хэндл модуля (исполняемого файла, *.exe или *.dll), в 
   // котором лежит ресурс. NULL означает модуль, ассоциированный
   //с текущим процессом, хотя в этом случае можно сразу вызывать
   //FindResource, передавая первым параметром NULL,
   // а под VCL можно использовать глобальную HInstance
   
HMODULE hMod=GetModuleHandle(NULL);
   
// если ресурс лежит в другом файле, то параметр для GetModuleHandle
   // можно получить с помощью LoadLibrary(...);
   
if(!hMod) {
       
//Обработка ошибки
   
}
   
//Получаем дескриптор информационного блока нашего ресурса
   
HRSRC hRes=FindResource(hMod,"ResurceName",RT_RCDATA);
   
//Если ResurceName не было определено как число, то ResurceName
   //берется в кавычках. Иначе надо (LPSTR)ResurceName
   //Если тип ресурса был задан как WAVE, то последний параметр должен
   // быть "WAVE" - в кавычках!
   
if(!hRes){
       
//Обработка ошибки
   
}
   
//Теперь загружаем ресурс в память, получая дескриптор загру-
   //женного блока памяти.
   
HGLOBAL hGlob=LoadResource(hMod,hRes);
   
//Опять же, для ресурса в "текущем" модуле, первым параметром можно
   //передавать NULL
   
if(!hGlob) {
       
//Обработка ошибки
   
}
   
//И, наконец, последнее - получаем указатель на начало массива
   
BYTE *lpbArray=(BYTE*)LockResource(hGlob);
   
if(!lpbArray) {
       
//Обработка ошибки
   
}


 

Использование извлеченного файла 

Мы представили ресурс как массив байт - и можем делать с ним то, что хотели. Записать на диск как файл: (способов куча, я использую те функции, к которым привык)

//где то наверху должны быть подключены
#include <stdio.h>
#include <fcntl.h>
#include <io.h>

   //Получаем размер массива (размер файла)
   
DWORD dwFileSize=SizeofResource(hMod,hRes);
   
if(!dwFileSize) {
       
//Обработка ошибки
   
}

   
int
   
hFile=open("AnyFileName",O_BINARY|O_CREAT|O_WRONLY,S_IWRITE);

   
if(k==-1) {
       
//Обработка ошибки
   
}
   
if(write(hFile,lpbArray,dwFileSize)==-1) {
       
close(hFile);
       
//Обработка ошибки;
   
}  
   
close(hFile);

Проиграть ресурс, (если, конечно, это был *.wav файл; причем не важно, как мы его объявляли - WAVE или RC_DATA)
//где то наверху должен быть подключен
#include <mmsystem.h>

   DWORD fdwSound = SND_NOSTOP | SND_ASYNC | SND_NODEFAULT | SND_MEMORY;
   
PlaySound(lpbArray, hMod, fdwSound);
   
// в контексте данного топика важным является флаг SND_MEMORY:
   // образ звука храниться в памяти

Под обработкой ошибки подразумевалось некоторое сообщение, если хочется, и, главное, НЕ выполнение последующего кода, иначе, в лучшем случае, при последующих вызовах функций API будут возвращаться ошибки (NULL), а могут случиться и более плачевные последствия

В приведенном коде использовались только функции API Windows и из стандартной сишной библиотеки, поэтому все должно работать и под VC, и под Builder'ом.