FAQ C++ BuilderConsultez toutes les FAQ

Nombre d'auteurs : 60, nombre de questions : 670, dernière mise à jour : 21 novembre 2010  Ajouter une question

 

Cette F.A.Q. a été réalisée à partir des questions fréquemment posées sur le forum C++ Builder de developpez.com et de l'expérience personnelle des auteurs.

Nous tenons à souligner que cette F.A.Q. ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette F.A.Q. ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez devenir rédacteur, contactez pottiez

Nous espérons que cette F.A.Q. saura répondre à un maximum de vos questions. Nous vous souhaitons une bonne lecture.

L'équipe C++ Builder de Developpez.

Commentez cette FAQ : Commentez


SommaireInterface bisRessources (3)
précédent sommaire suivant
 

Les fichiers exécutables contiennent tous un fichier ressource, visible avec un explorateur de ressources (type RESEXPLORER). Ce fichier contient les données utiles à l'exécutable, comme par exemple son icône.
Il est possible d'ajouter ou de modifier cette ressource pour inclure des fichiers que l'on ne souhaite pas "voir traîner", par exemple contenant des mots de passe.

Dans un premier temps, l'exécutable étant en cours, nous n'avons pas les droits d'accès. Il est nécessaire de les obtenir pour mettre à jour l'application. Pour cela, nous allons effectuer une copie de l'exécutable au même endroit que celui en cours (donc transparent pour l'utilisateur). L'original en exécution sera au préalable déplacé dans le dossier temporaire, puis supprimé.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
AnsiString TempPath; 
AnsiString NewPath; 
AnsiString OriginalPath; 
  
//move running application 
GetTempPath(200,TempPath.c_str()); 
GetTempFileName(TempPath.c_str(), _T("TMP"),0,NewPath.c_str()); 
OriginalPath = Application->ExeName; 
  
if(MoveFileEx(OriginalPath.c_str(),NewPath.c_str(),MOVEFILE_REPLACE_EXISTING) == FALSE) 
    ShowMessage("Moving file error"); 
if(CopyFile(NewPath.c_str(),OriginalPath.c_str(),FALSE) == FALSE) 
    ShowMessage("Copying file error"); 
if(MoveFileEx(NewPath.c_str(),NULL,MOVEFILE_DELAY_UNTIL_REBOOT) == FALSE) 
    ShowMessage("Moving file error");
Comme il n'est pas possible à l'exécutable de se supprimer lui-même, il sera supprimé au redémarrage du PC par la fonction MoveFileEx en donnant le message MOVEFILE_DELAY_UNTIL_REBOOT.

Une fois les droits acquis, il n'y a plus qu'à charger le fichier à mettre en ressource puis de mettre à jour.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
DWORD dwFileSize, dwBytesRead,dwBytesWritten; 
LPBYTE lpBuffer; 
  
//récupération du fichier à ajouter en ressource 
HANDLE hFile = CreateFile(Chemin_Fichier_Text.c_str(), 
                                  GENERIC_READ, 
                                  0, 
                                  NULL, 
                                  OPEN_EXISTING,  
                                  FILE_ATTRIBUTE_NORMAL, 
                                  NULL); 
  
if(INVALID_HANDLE_VALUE != hFile) 
{ 
    //chargement du fichier dans un buffer pour le transmettre 
    dwFileSize = GetFileSize(hFile, NULL); 
    lpBuffer = new BYTE[dwFileSize]; 
    if(ReadFile(hFile, 
        lpBuffer, 
        dwFileSize, 
        &dwBytesRead, 
        NULL) != FALSE) 
    { 
        //récupération du Handle de la ressource 
        HANDLE hResource = BeginUpdateResource(OriginalPath.c_str(), FALSE); 
        if(NULL != hResource) 
        { 
            //mise à jour 
            if(UpdateResource(hResource, 
                RT_RCDATA, 
                "RESOURCEADDED", 
                MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL), 
                (LPVOID) lpBuffer, 
                dwFileSize) != FALSE) 
            { 
                if(EndUpdateResource(hResource, FALSE) != FALSE) 
                    ShowMessage("Update succed! Please restart application"); 
                else 
                    ShowMessage("Error "+IntToStr(GetLastError())); 
            } 
        }               
    } 
    delete [] lpBuffer; 
    CloseHandle(hFile); 
}
Le fichier mis à jour se trouvant sur la copie, il faut donc relancer l'application pour voir l'effet de cette mise à jour. Ici le fichier ajouté (ou modifié s'il existe déjà sous le même nom RESOURCEADDED) est de type RCDATA.

Mis à jour le 6 décembre 2006 bandit boy

Il suffit d'utiliser les classes TResourceStreamet TStringList comme suit :

Code c++ : Sélectionner tout
1
2
3
4
5
6
AnsiString Chemin_Fichier_Text=ExtractFilePath(Application->ExeName)+"\\file.txt"; 
TResourceStream *MRes=new TResourceStream((int)HInstance, "RESOURCE", RT_RCDATA); 
MRes->SaveToFile(Chemin_Fichier_Text); 
TStringList *File= new TStringList; 
File->LoadFromFile(Chemin_Fichier_Text); 
DeleteFile(Chemin_Fichier_Text);
Ici on écrit dans un fichier temporaire le contenu de la resource "RESOURCE", puis on le charge dans un TStringList pour utilisation.

Mis à jour le 6 décembre 2006 Interruption13h

L'idée développée est d'enregistrer un fichier (bmp, gif, csv ...) en ressource, quel que soit son type.

Il se peut que durant une application, on souhaite sauver des fichiers, des configurations ou tout autres fichiers qui ne puissent pas être pré-chargés durant la création de l'application.

Dans l'exemple suivant, on sauvegarde le fichier en ressource, l'important est de passer par le type TStream, pour le sauver en RC_DATA.

Pour l'enregistrer:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
TMemoryStream *image = new TMemoryStream(); 
Image1->Picture->Graphic->SaveToStream(image); 
image->Position = 0; 
  
//procédure de sauvegarde 
AnsiString TempPath,NewPath,OriginalPath; 
  
GetTempPath(200,TempPath.c_str()); 
GetTempFileName(TempPath.c_str(), "TMP",0,NewPath.c_str()); 
OriginalPath = Application->ExeName; 
  
if(MoveFileEx(OriginalPath.c_str(),NewPath.c_str(),MOVEFILE_REPLACE_EXISTING) == FALSE) 
    Application->MessageBox("Impossible de déplacer l'exe","Erreur",MB_OK+MB_ICONWARNING); 
if(CopyFile(NewPath.c_str(),OriginalPath.c_str(),FALSE) == FALSE) 
    Application->MessageBox("Impossible de copier l'exe","Erreur",MB_OK+MB_ICONWARNING); 
if(MoveFileEx(NewPath.c_str(),NULL,MOVEFILE_DELAY_UNTIL_REBOOT) == FALSE) 
    Application->MessageBox("Impossiblede déplacer la copie","Erreur",MB_OK+MB_ICONWARNING); 
  
DWORD dwFileSize, dwBytesRead,dwBytesWritten; 
LPBYTE lpBuffer; 
  
HANDLE hResource = BeginUpdateResource(OriginalPath.c_str(), FALSE); 
if(NULL != hResource) 
{ 
    if(UpdateResource(hResource,RT_RCDATA,"IMAGEBMP",MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),(LPVOID)image->Memory, (DWORD)image->Size) != FALSE) 
    { 
          if(EndUpdateResource(hResource, FALSE) == FALSE) 
              ShowMessage("Error "+IntToStr(GetLastError())); 
    } 
    else 
          ShowMessage("Error "+IntToStr(GetLastError())); 
} 
delete image;

Pour le recharger, il suffit de lire le fichier en tant que TRessourceStream, de le convertir en TSream pour obtenir le format de sauvegarde, puis de sauver le fichier en tant que son propre type (".txt" pour les fichier texte, ".csv" pour les csv ...)

Pour le recharger :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
hnd = FindResource(  NULL, "IMAGEBMP", RT_RCDATA); 
if(hnd != NULL) 
{ 
      //chargement de la ressource 
      TResourceStream *Res=new TResourceStream((int)HInstance,"IMAGEBMP",RT_RCDATA); 
      TMemoryStream *image = new TMemoryStream(); 
      //conversion de la ressource en TMemoryStream pour retrouver le même format enregistré 
      Res->SaveToStream(image); 
      image->Position = 0; 
      //sauvegarde de l'image dans un fichier pour la recharger plus facilement 
      image->SaveToFile("image1.bmp"); 
      //supression de l'image et des variables 
      Image1->Picture->Bitmap->LoadFromFile("image1.bmp"); 
      DeleteFile("image1.bmp"); 
      delete Res; 
      delete image; 
}

Par exemple dans une application multilangue, on peut sauver dans un fichier ini, txt ou autre les configurations (choix de la langue, fichiers chargés, modifications apportées par l'utilisateur...) puis le sauver en Ressource pour que l'exe soit portable.

L'avantage de cette manipulation est que TOUT est dans UN fichier : l'application elle-même.
L'inconvénient est que le code est un peu lourd à placer, et qu'il faut que l'application soit modifiable (non en lecture seule) pour être modifiée.

Mis à jour le 10 décembre 2007 bandit boy pottiez

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2020 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.