web-dev-qa-db-fra.com

Incorporer un fichier texte dans une ressource dans une application Windows native

J'ai un programme Windows C++. J'ai un fichier texte qui contient des données. Actuellement, le fichier texte est un fichier distinct et il est chargé au moment de l'exécution et analysé. Comment est-il possible d'intégrer cela dans le binaire en tant que ressource?

46
Oliver Zheng

Puisque vous travaillez sur une application Windows native, ce que vous voulez faire est de créer une ressource définie par l'utilisateur pour incorporer le contenu du fichier texte dans la ressource compilée.

Le format d'une ressource définie par l'utilisateur est documenté sur MSDN , tout comme les fonctions de chargement .

Vous intégrez votre fichier texte dans un fichier de ressources comme celui-ci:

nameID typeID filename

nameID est un entier non signé 16 bits unique qui identifie la ressource et typeID est un entier non signé 16 bits supérieur à 255 qui identifie le type de ressource (vous pouvez définir ces entiers dans le resource.h Fichier). filename est le chemin d'accès au fichier dont vous souhaitez incorporer le contenu binaire dans la ressource compilée.

Vous pourriez donc l'avoir comme ceci:

Dans resource.h:

// Other defines...

#define TEXTFILE        256
#define IDR_MYTEXTFILE  101

Dans votre fichier de ressources:

#include "resource.h"

// Other resource statements...

IDR_MYTEXTFILE TEXTFILE "mytextfile.txt"

Ensuite, vous le chargez comme ceci (code de vérification d'erreur omis pour plus de clarté):

#include <windows.h>
#include <cstdio>
#include "resource.h"

void LoadFileInResource(int name, int type, DWORD& size, const char*& data)
{
    HMODULE handle = ::GetModuleHandle(NULL);
    HRSRC rc = ::FindResource(handle, MAKEINTRESOURCE(name),
        MAKEINTRESOURCE(type));
    HGLOBAL rcData = ::LoadResource(handle, rc);
    size = ::SizeofResource(handle, rc);
    data = static_cast<const char*>(::LockResource(rcData));
}

// Usage example
int main()
{
    DWORD size = 0;
    const char* data = NULL;
    LoadFileInResource(IDR_MYTEXTFILE, TEXTFILE, size, data);
    /* Access bytes in data - here's a simple example involving text output*/
    // The text stored in the resource might not be NULL terminated.
    char* buffer = new char[size+1];
    ::memcpy(buffer, data, size);
    buffer[size] = 0; // NULL terminator
    ::printf("Contents of text file: %s\n", buffer); // Print as ASCII text
    delete[] buffer;
    return 0;
}

Notez que vous n'avez pas réellement à libérer la ressource car la ressource réside dans le binaire de l'exécutable et le système les supprimera automatiquement à la fin du programme (la fonction FreeResource() ne fait rien sur 32 bits et Systèmes Windows 64 bits).

Étant donné que les données résident dans le binaire exécutable, vous ne pouvez pas les modifier directement via le pointeur récupéré (c'est pourquoi l'implémentation de la fonction LoadFileInResource() stocke le pointeur dans un const char*). Pour ce faire, vous devez utiliser les fonctions BeginUpdateResource(), UpdateResource() et EndUpdateResource().

66
In silico