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


SommaireGestion des fichiersRépertoires (15)
précédent sommaire suivant
 

Suivant les installations, le répertoire de Windows peut se trouver à différents chemins. Il est donc impératif, lorsqu'on doit y faire référence, de le demander au système. Pour cela, on utilise l'API Win32 GetWindowsDirectory. Cette API prend comme premier argument un buffer de caractères, et comme second sa taille en caractères.
La fonction retourne :

  • 0 en cas d'erreur
  • la taille de la chaîne retournée (sans le caractère de terminaison) en cas de succès
  • la taille du buffer à allouer si le buffer est trop petit pour contenir la chaîne. Il est recommandé que le premier appel se fasse avec une longueur de buffer de MAX_PATH, constante Windows.


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
AnsiString RepertoireWindows() 
{ 
  AnsiString result = ""; 
  UINT buflength; 
  char *repertoire = new char[MAX_PATH]; 
  buflength = GetWindowsDirectory(repertoire,MAX_PATH); 
  if (buflength == 0) 
  { 
    delete[] repertoire; 
    return result; 
  } 
  else if (buflength > MAX_PATH) 
  { 
    delete[] repertoire; 
    repertoire = new char[buflength]; 
    GetWindowsDirectory(repertoire,buflength); 
  } 
  result = repertoire; 
  delete[] repertoire; 
  return result; 
}
Une autre solution, qui utilise les variables d'environnement :

Code c++ : Sélectionner tout
1
2
3
4
AnsiString RepertoireWindows() 
{ 
  getenv("WINDIR"); 
}

Mis à jour le 1er septembre 2004 Greybird

Suivant les installations, le répertoire de Windows peut se trouver à différents chemins. Il est donc impératif, lorsqu'on doit y faire référence, de le demander au système. Pour cela, on utilise l'API Win32 GetSystemDirectory. Cette API prend comme premier argument un buffer de caractères, et comme second sa taille en caractères.
La fonction retourne :

  • 0 en cas d'erreur
  • la taille de la chaîne retournée (sans le caractère de terminaison) en cas de succès
  • la taille du buffer à allouer si le buffer est trop petit pour contenir la chaîne. Il est recommandé que le premier appel se fasse avec une longueur de buffer de MAX_PATH, constante Windows.

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
AnsiString RepertoireSystemeWindows() 
{ 
  AnsiString result = ""; 
  UINT buflength; 
  char *repertoire = new char[MAX_PATH]; 
  buflength = GetSystemDirectory(repertoire,MAX_PATH); 
  if (buflength == 0) 
  { 
    delete[] repertoire; 
    return result; 
  } 
  else if (buflength > MAX_PATH) 
  { 
    delete[] repertoire; 
    repertoire = new char[buflength]; 
    GetSystemDirectory(repertoire,buflength); 
  } 
  result = repertoire; 
  delete[] repertoire; 
  return result; 
}

Mis à jour le 1er septembre 2004 Greybird

Suivant les installations, le répertoire de Windows peut se trouver à différents chemins. Il est donc impératif, lorsqu'on doit y faire référence, de le demander au système. Pour cela, on utilise l'API Win32 GetTempPath. Cette API prend comme second argument un buffer de caractères, et comme premier sa taille en caractères.
La fonction retourne :

  • 0 en cas d'erreur
  • la taille de la chaîne retournée (sans le caractère de terminaison) en cas de succès
  • la taille du buffer à allouer si le buffer est trop petit pour contenir la chaîne. Il est recommandé que le premier appel se fasse avec une longueur de buffer de MAX_PATH, constante Windows.

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
AnsiString RepertoireTemporaire() 
{ 
  AnsiString result = ""; 
  UINT buflength; 
  char *repertoire = new char[MAX_PATH]; 
  buflength = GetTempPath(MAX_PATH, repertoire); 
  if (buflength == 0) 
  { 
    delete[] repertoire; 
    return result; 
  } 
  else if (buflength > MAX_PATH) 
  { 
    delete[] repertoire; 
    repertoire = new char[buflength]; 
    GetTempPath(buflength, repertoire); 
  } 
  result = repertoire; 
  delete[] repertoire; 
  return result; 
}

Mis à jour le 1er septembre 2004 Greybird

On a souvent besoin d'accéder à un fichier situé dans le répertoire de l'exécutable. Mais ce répertoire peut changer selon les ordinateurs... Il peut paraître plus simple d'omettre le chemin lorsqu'on fait référence à un fichier se trouvant dans le répertoire de l'application :

Code c++ : Sélectionner tout
ChargerConfiguration("options.ini");
Dans ce cas, le fichier est cherché dans le répertoire courant de l'application. Mais ce répertoire peut être changé (regardez les raccourcis Windows et leur propriété Démarrer en). Il est donc nécessaire de trouver le répertoire de l'application, ce qui se fait à l'aide de la fonction ExtractFilePath de la manière suivante :

Code c++ : Sélectionner tout
AnsiString RepertoireApplication = ExtractFilePath(Application->ExeName);
Notez que Application->ExeName contient le nom de fichier exécutable de l'application. La fonction ExtractFilePath en extrait le chemin. Donc pour notre petit exemple, nous utiliserions :

Code c++ : Sélectionner tout
ChargerConfiguration(ExtractFilePath(Application->ExeName)+"options.ini");

Mis à jour le 1er septembre 2004 Geronimo

On voit souvent cette petite boîte de dialogue très pratique dans les programmes d'installation, lorsqu'il s'agit de choisir le répertoire où sera déployé le logiciel. Cette petite boîte de dialogue peut-être affichée par le code suivant :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
#include <FileCtrl.hpp> 
// ... 
AnsiString Directory; 
if (SelectDirectory("Sélectionnez le répertoire de copie", "c:\\", Directory)) 
{ 
    ShowMessage("Vous avez choisi : "+Directory); 
} 
else 
{ 
    ShowMessage("Vous avez annulé"); 
}
La fonction SelectDirectory, définie dans FileCtrl.hpp, prend pour premier argument la légende de la fenêtre. Le second argument est le répertoire par défaut. Enfin, le troisième argument est la chaîne AnsiString dans laquelle sera stocké le répertoire. La fonction SelectDirectory retourne true si l'utilisateur valide avec OK. Sinon, elle retourne false.

Une autre solution consiste à utiliser "BrowseForFolder" de l'API Windows, comme suit pour une fenêtre centrée :

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
//--------------------------------------------------------------------------- 
#define NO_WIN32_LEAN_AND_MEAN  // à mettre avant '#include <vcl.h>' 
#include <vcl.h> 
#pragma hdrstop 
#include <shlobj.h>           
  
#include "Unit1.h" 
//--------------------------------------------------------------------------- 
#pragma package(smart_init) 
#pragma resource "*.dfm" 
TForm1 *Form1; 
  
//--------------------------------------------------------------------------- 
// Fonction Globale 
//--------------------------------------------------------------------------- 
int __stdcall BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) 
{  // Permet de centrer la boite à l'ecran 
    TRect rect; 
    GetWindowRect(hwnd, &rect); 
  
    MoveWindow( 
        hwnd, 
        ( Screen->Width - rect.Width() ) /2, // centré en x 
        ( Screen->Height - rect.Height() ) /2, 
        rect.Width(), 
        rect.Height(), 
        true 
    ); 
    return 1; 
} 
  
  
//--------------------------------------------------------------------------- 
__fastcall TForm1::TForm1(TComponent* Owner) 
   : TForm(Owner) 
{ 
} 
//--------------------------------------------------------------------------- 
String __fastcall TForm1::SelectDossier( String Titre ) 
{ 
    char Path[MAX_PATH]; 
    char BufferDisplayName[MAX_PATH]; 
  
    PItemIDList IDRoot; 
    SHGetSpecialFolderLocation(Handle, CSIDL_NETWORK, &IDRoot); 
  
    TBrowseInfo BrowseInfo; 
    ZeroMemory(&BrowseInfo, sizeof(TBrowseInfo)); 
    BrowseInfo.hwndOwner       = Handle; 
    BrowseInfo.pszDisplayName  = BufferDisplayName; 
    BrowseInfo.lpszTitle       = Titre.c_str(); 
    BrowseInfo.ulFlags         = BIF_DONTGOBELOWDOMAIN | BIF_RETURNONLYFSDIRS | BIF_RETURNFSANCESTORS; 
    BrowseInfo.lpfn            = BrowseCallbackProc; 
  
    PItemIDList PList          = SHBrowseForFolder(&BrowseInfo); 
  
    if (PList){ 
        SHGetPathFromIDList(PList, Path); 
        return (String)Path; 
    } 
    else return ""; 
} 
//--------------------------------------------------------------------------- 
void __fastcall TForm1::Button1Click(TObject *Sender) 
{ 
    String PathSelect  = SelectDossier( "Veuillez-sélectionner le dossier source :" ); 
} 
//---------------------------------------------------------------------------

Mis à jour le 1er septembre 2004 Dure_Limite Geronimo

Utilisez pour cela fonction CreateDirectory.

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
if (CreateDirectory(Repertoire.c_str(), 0)) 
{ 
    // Le répertoire a été créé 
} 
else 
{ 
    // Le répertoire n'a pas été créé 
}

Mis à jour le 1er septembre 2004 Geronimo

La fonction CreateDirectory n'est pas capable de créer plusieurs répertoires à la fois. Si vous voulez créer le répertoire c:\temp\mon_application, il faut que le répertoire temp existe déjà. Utilisez ForceDirectories, définie dans l'unité FileCtrl ou SysUtils pour créer le chemin en une seule fois :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
#include <FileCtrl.hpp> 
//... 
if (ForceDirectories(Chemin) 
{ 
   // Le chemin a été créé 
} 
else 
{ 
   // Le chemin n'a pas été créé 
}

Mis à jour le 1er septembre 2004 Geronimo

Faites appel à la fonction DirectoryExists définie dans l'unité FileCtrl.

Code c++ : Sélectionner tout
1
2
3
4
5
#include <FileCtrl.hpp> 
if (DirectoryExists(Repertoire)) 
{ 
  //... 
}

Mis à jour le 1er septembre 2004 Geronimo

Vous pouvez utiliser la fonction MoveFile qui est également valable pour les fichiers.

Code c++ : Sélectionner tout
BOOL MoveFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName);
Exemple:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
AnsiString  OldPath = "C:\\Test\\", NewPath = "C:\\Temp\\Test\\"; 
if(MoveFile(OldPath.c_str(), NewPath.c_str()) == true) 
{ 
   //Réperoire déplacé avec succès 
} 
else 
{ 
   //Problème 
}

Mis à jour le 25 avril 2005 Neo41

Vous pouvez utiliser la fonction RenameFile qui est également valable pour les fichiers.

Code c++ : Sélectionner tout
bool __fastcall RenameFile(const AnsiString OldName, const AnsiString NewName);
Exemple:

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
AnsiString  OldName = "C:\\Ancien\\", NewName = "C:\\Nouveau\\"; 
if(RenameFile(OldName, NewName) == true) 
{ 
    //Réperoire renommé avec succès 
} 
else 
{ 
    //Problème 
}

Mis à jour le 25 avril 2005 Neo41

Pour réaliser la suppression d'un répertoire, plusieurs approches sont possibles selon que le répertoire est vide ou pas.

  • Utiliser RemoveDir et RemoveDirectory

Ces fonctions sont valides uniquement pour un répertoire vide

Code c++ : Sélectionner tout
1
2
bool __fastcall RemoveDir(const AnsiString Dir); 
BOOL RemoveDirectory(LPCTSTR lpPathName);
Exemple:

Code c++ : Sélectionner tout
1
2
AnsiString MyPath = "C:\\Temp\\"; 
RemoveDir(MyPath);
  • Utiliser l'API SHFILEOPSTRUCT

Pour l'utiliser il ne faut pas oublier #include "ShellApi.h"

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
#include "ShellApi.h" 
-------------------------------------------------------------------- 
SHFILEOPSTRUCT stFileOp; 
ZeroMemory(&stFileOp, sizeof(stFileOp)); 
stFileOp.wFunc = FO_DELETE; 
stFileOp.fFlags = FOF_SILENT | FOF_NOCONFIRMATION; 
stFileOp.hwnd = Application->Handle; 
stFileOp.pFrom = "C:\\Temp\0"; 
  
SHFileOperation(&stFileOp);
  • Ecrire une fonction récursive

Le but de cette fonction est de parcourir de façon récursive tous les fichiers et les sous réperoires du répertoire à supprimer. La fonction pourrait ressembler à ceci:

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
void __fastcall DeleteRecursif(AnsiString pmRep) 
{ 
   TSearchRec SearchRec; 
   int Attributes = 0; 
   AnsiString bcRep = "", 
              bcRepTemp = "", 
              bcFile = ""; 
  
   Attributes |= faAnyFile; 
   bcRep = pmRep; 
   if(bcRep[bcRep.Length()] != '\\') 
   { 
      bcRep+= "\\"; 
   } 
   bcRepTemp = bcRep; 
   bcRep+= "*.*";      
   if(FindFirst(bcRep, Attributes, SearchRec) == 0) 
   { 
      do 
      { 
         bcFile = SearchRec.Name; 
         if(bcFile != "." && bcFile != "..") 
         { 
            bcFile = bcRepTemp + SearchRec.Name; 
            if(SearchRec.Attr != faDirectory) 
            { 
               DeleteFile(bcFile); 
            } 
            else 
            { 
               DeleteRecursif(bcFile); 
            } 
         } 
      } 
      while (FindNext(SearchRec) == 0); 
      FindClose(SearchRec); 
   } 
   RemoveDir(pmRep); 
}
Et pour supprimer un répertoire il suffit d'appeler cette fonction:

Code c++ : Sélectionner tout
DeleteRecursif("C:\\Temp\\");

Mis à jour le 25 avril 2005 Neo41

Il est impossible d'utiliser la fonction FileAge sur un répertoire, la valeur de retour étant alors -1, soit fichier inexistant.

L'astuce consiste à passer par les méthodes de recherche de fichiers, et de récupérer les données retournées par cette recherche, comme le montre le code suivant :

Code c++ : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
TSearchRec SR; 
String NomRepertoire = "C:\\jeux"; 
TDateTime DT; 
  
if (!FindFirst(NomRepertoire, faDirectory, SR)) 
{ 
   // on convertit le marqueur horaire système du répertoire en une date classique 
   DT = FileDateToDateTime(SR.Time); 
   ShowMessage(DT); 
} 
else 
{ 
   ShowMessage("répertoire inexistant"); 
}
Le deuxième paramètre de la fonction FindFirst permet de spécifier le type de fichier recherché (ici répertoire). Si celui-ci est trouvé, les informations le concernant sont renvoyées dans la variable SR.

Mis à jour le 21 juin 2006 Gilles Louïse Sunchaser

Pour obtenir le chemin d'accès à ces répertoires, il faudra utiliser deux fonctions des API Windows :

  • SHGetSpecialFolderLocation
  • SHGetPathFromIDList

Pour ce faire et dans le cas d'une inclusion d'en tête de la VCL, il faut respecter l'ordre de déclaration suivant :

Code c++ : Sélectionner tout
1
2
#define NO_WIN32_LEAN_AND_MEAN 
#include <vcl.h>
On peut donc créer une fonction utilisant ces deux API.

Code c++ : Sélectionner tout
1
2
private:// Déclarations de l'utilisateur 
String __fastcall CheminSpecialFolder(int TypeFolder);
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
String __fastcall TForm::CheminSpecialFolder(int TypeFolder) 
{ 
    String Result = ""; 
    // 
    char sPath[MAX_PATH]; 
    _ITEMIDLIST *AIdList; 
    // 
    try 
    { 
        SHGetSpecialFolderLocation(Application->Handle, TypeFolder, &AIdList); 
        SHGetPathFromIDList(AIdList, sPath); 
        Result = sPath; 
    } 
    catch(...) 
    { 
        //gérer les erreurs relevées... 
    } 
    // 
    return Result; 
}
Cette fonction peut être appelée simplement par :

Code c++ : Sélectionner tout
1
2
3
4
void __fastcall TForm::ButtonClick(TObject *Sender) 
{ 
ShowMessage(CheminSpecialFolder(CSIDL_COMMON_DESKTOPDIRECTORY)); 
}
Les valeurs représentant les différents types de dossiers sont disponibles dans l'aide SDK Windows.

Pour récupérer le répertoire temporaire de l'OS, vous pouvez vous en sortir avec les lignes suivantes :

Code c++ : Sélectionner tout
1
2
AnsiString TempPath; 
GetTempPath(200,TempPath.c_str());

Mis à jour le 6 décembre 2006 atlantis bandit boy Sunchaser

Pour obtenir le nom court d'un fichier, on utilise la fonction GetShortPathName.

Code c++ : Sélectionner tout
1
2
3
4
5
6
String __fastcall TForm1::Path_LongToCourt( String Path_Long ) 
{ 
   char PathCourt[MAX_PATH]; 
   GetShortPathName(Path_Long.c_str(), PathCourt, MAX_PATH); 
   return (String)PathCourt; 
}
Exemple : le path court de C:\\Program Files\\Borland\\CBuilder6\\Projects donnera C:\\Progra~1\\Borland\\CBuild~1\\Projects.

Mis à jour le 6 décembre 2006 Dure_Limite

La procédure est similaire à celle mentionnée pour les fichiers.

Mis à jour le 6 décembre 2006 Dure_Limite

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.