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
- Comment obtenir le répertoire de Windows ?
- Comment obtenir le répertoire système de Windows ?
- Comment obtenir le répertoire temporaire de Windows ?
- Comment obtenir le répertoire dans lequel est situé le programme exécutable ?
- Comment ouvrir la boîte de dialogue demandant à l'utilisateur la sélection d'un répertoire ?
- Comment créer un répertoire ?
- Comment créer un chemin complet en une seule fois
- Comment savoir si un répertoire existe ?
- Comment déplacer un répertoire ?
- Comment renommer un répertoire ?
- Comment supprimer un répertoire ?
- Comment obtenir la date de création d'un répertoire ?
- Comment trouver les répertoires spéciaux de Windows ?
- Comment obtenir le nom court d'un dossier ?
- Comment obtenir la taille, dates et attributs d'un dossier ?
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; } |
Code c++ : | Sélectionner tout |
1 2 3 4 | AnsiString RepertoireWindows() { getenv("WINDIR"); } |
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; } |
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; } |
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");
Code c++ : | Sélectionner tout |
AnsiString RepertoireApplication = ExtractFilePath(Application->ExeName);
Code c++ : | Sélectionner tout |
ChargerConfiguration(ExtractFilePath(Application->ExeName)+"options.ini");
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é"); } |
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 :" ); } //--------------------------------------------------------------------------- |
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éé } |
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éé } |
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)) { //... } |
Vous pouvez utiliser la fonction MoveFile qui est également valable pour les fichiers.
Code c++ : | Sélectionner tout |
BOOL MoveFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName);
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 } |
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);
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 } |
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); |
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); } |
Code c++ : | Sélectionner tout |
DeleteRecursif("C:\\Temp\\");
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"); } |
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> |
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; } |
Code c++ : | Sélectionner tout |
1 2 3 4 | void __fastcall TForm::ButtonClick(TObject *Sender) { ShowMessage(CheminSpecialFolder(CSIDL_COMMON_DESKTOPDIRECTORY)); } |
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()); |
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; } |
La procédure est similaire à celle mentionnée pour les fichiers.
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 çaLes 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 © 2024 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.