V tomto článku popíšem veľmi užitočný postup a kód nad ktorým sa určite zamýšľal každý kóder.

Videli ste samostatný spustiteľný súbor, ktorý po spustení vytvoril napríklad obrázky, nakopíroval zo seba súbory, alebo sám zo seba vyexportoval pesničku, ktorú následne spustil?

Zamýšlali ste sa, ako do aplikácie pridať neaké ďalšie súbory bez toho, aby museli byť pribalené, alebo aby celý projekt bol zkomprimovaný v jednej spoločnej zložke?... V tomto článku si to popíšeme.


Ide o takzvaný Resources, kedy vložíme neaký súbor (respektíve obsah súboru - hudba, obrázky, text), do vytvoreného projektu - exe súbor, knižnica dll a podobne.
Inými slovami, chceme vytvoriť, v našom prípade, spustiteľný konzolový .exe súbor, ktorý po spustení napríklad vytiahne sám zo seba neaké iné súbory a uloží ich niekam na disk, prípadne nainštaluje.

Príklad použitia:
Mám program, ktorý má 5 častí, a tie musí prekopírovať niekam do systému. Za klasíckych okolností, by sme týchto 5 častí museli mať napríklad v jednej spoločnej zložke, odkiaľ by ich materský súbor nakopíroval do systému, prípadne by boli upnuté niekde na ftp, odkiaľ by ich materský súbor stiahol.

Použitie Resources nám umožňuje nahrať týchto 5 častí priamo do kódu materského súbora, ktorý ich po spustení načíta a prípadne ich uloží.

Výhodou je, že súbory sú uložené v kóde materského súboru a tým pádom pre okolie neviditeľné.


Tak ako všetko, aj pri postupe písania takejto aplikačky sa nám smer vetví na dve časti.

V prvej časti je nutné správnym spôsobom vložiť/importovať súbory do projektu. Pri vkladaní si súbory premenujeme na neaký typ, ktorý Visual Studio nepozná, napríklad, súbor obrazok.jpg premenujeme na typ .diall --> obrazok.diall a ten importujeme.
Nakoľko ide o nepodporovaný typ súboru .diall, Visual Studio nás vyzve k zadaniu nového typu.

Pri výzve vložíme do Visual Studia náš nový typ DIALL, s ktorým budeme pracovať.


V druhej časti je nutné naprogramovať priamo do projektu funkciu, ktorá nám daný súbor v Resources nájde, otvorí, vytiahnie nám z nej dáta a spracuje.

Je nutné si uvedomiť, že súbory nemusíme vložiť len do Resources importovaných priamo v .exe súbore. Môžme vytvoriť Resources, napríklad, v knižnici .dll, do nej importovať x súborov a z projektu .exe k nim pristupovať, spracovávať, kopírovať, inštalovať.


Pri návrhu funkcie použijeme prístup cez WinAPI.


Návrh funkcie:

main.c

void Load_Resource(int id, LPCWSTR section, LPCWSTR path)
{
    HRSRC dResource = FindResource(NULL,MAKEINTRESOURCE(id),section); //Najdi resource//
    HGLOBAL dGlobal =LoadResource(NULL, dResource); //Nacitaj zdroj - resource//
    BYTE* dData = (BYTE*)LockResource(dGlobal); //Nacitaj data zo droja - resource//
    int size = SizeofResource(NULL, dResource); //Zisti velkost zdroja - resource//


    //Definovanie vystupneho suboru (path) a ulozenie donho nacitanych dat//
    std::fstream save_file;
    save_file.open(path, std::ios::out | std::ios::binary);
    save_file.write((const char*)dData, size);

    FreeResource(dGlobal); //Free loaded resource//

}



Myslím si, že navrhnutý kód je viac než jasný.

FindResource pristupuje k inštancií zdroja, v ktorom sa resource nachádza. Premenná id reprezentuje definované
                       makro (číselnú hodnotu), ako označenie daného súbora a premenná section obsahuje Typ
                       uloženej Resource, v našom prípade DIALL.

LoadResource načíta nájdenú Resource v danej inštancií zdroja.
LockResource reprezentuje časť (dáta) "vyťahovaného" súboru v dátovom zdroji Resource. Túto čast uloží do
                        premennej dData ako pointer typu BYTE, ukazujúci do tejto časti.
SizeofResource je schopná zistiť veľkosť danej dátovej časti inštancie zdroja.
FreeResource uvoľní z pamäti načítaný zdroj resource.

Pripomeniem, že inštancia zdroja je v našom prípade NULL.
Znamená to, že ako inštancia je použitý odkaz na projekt konzolovej aplikácie - "seba sama", teda na súbor .exe, v ktorom máme Resource uloženú.

Pokiaľ by sme chceli Resource načitávať z iného zdroja, tak namiesto NULL použijeme inštanciu napríklad v podobe :

 

HMODULE dRes = LoadLibrary("MyResources.dll") HRSRC dResource = FindResource (dRes,MAKEINTRESOURCE(id), section);
// ... //

 

Operáciu uloženia dát do definovaného súboru snáď není nutné popisovať.

Pokiaľ by sme mali projekt ako WinForm a chceli by sme zobraziť uloženú fotku v novom okne Formu, tak dáta z načítanej Resource ukladať nebudeme, ale naplníme nimi daný PictureBox.


Zbežne sme si veci popísali, vysvetlili, navrhli sme funkciu načítania dát zo droja Resource, môžme sa teda vrhnúť na video-ukážku, na ktorej som všetko názorne odsimuloval a vytvoril: