C/C++ Programmierung: Durchsuchen eines Programmordners und Auswählen einer Datei

Im Animation Pose/Skeleton Modeller-Programmbeispiel ist es möglich, unterschiedliche 3D-Modelle samt Animations-Skelett sowie unterschiedliche Animationsposen zu laden. Bevor nun eine Datei geöffnet und ausgelesen werden kann, muss sie zunächst einmal vom Benutzer des Programms ausgewählt werden. Zuständig hierfür sind im besagten Programmbeispiel die beiden Funktionen Select_NewModelAndSkeleton() sowie Select_NewAnimationPose(), denen als Parameter der jeweilige Verzeichnispfad des zu durchsuchenden Programmordners zu übergeben ist. Da beide Funktionen vom Aufbau her völlig identisch sind, genügt es, wenn wir unser Augenmerk lediglich auf eine der Funktionen richten:


#define MaxLength 100

char
g_AnimationPoseName[MaxLength];
char g_AnimationPoseFileName[2*MaxLength];

// aktuelle Schreibe-Position, wird zum Ändern des
// Dateinamens benötigt:
long g_AnimationPoseNameWritePos;

// Index der vom Benutzer ausgewählten Datei:
long g_NewAnimationPoseFileNr = 1;

// Index der zuvor ausgewählten Datei:
long g_NewAnimationPoseFileNrLastFrame = 0;

// Hinweis:
// Nur wenn der Benutzer eine neue Datei auswählt, muss die
// Select_NewAnimationPose() aufgerufen werden:

if(g_NewAnimationPoseFileNrLastFrame != g_NewAnimationPoseFileNr)
    Select_NewAnimationPose(g_AnimationPoseFileDirectory);

. . .

// Die nachfolgende Funktion speichert den Namen der vom Benutzer
// ausgewählten Datei im g_AnimationPoseName-Array sowie den Dateinamen
// samt Dateipfad im g_AnimationPoseFileName-Array.
// Diese Informationen sind zum Laden der betreffenden Datei erforderlich!

void
Select_NewAnimationPose(char* pDirectory)
{
    long   hFile;                 // wichtig für
    struct _finddata_t c_file;    // das Datei-Management

    char strBuffer[200];
    char TempFileName[MaxLength];

    long SavedNewFileNr = 0; // Dateinummer
    long WritePos = 0;

    sprintf(strBuffer, "%s*", pDirectory);

    if((hFile = _findfirst(strBuffer, &c_file )) != -1L)
    {
        while(_findnext( hFile, &c_file ) == 0)
        {
            // Die vom Benutzer ausgewählte Datei ist gefunden:
            if(SavedNewFileNr == g_NewAnimationPoseFileNr)
            {
                if(c_file.name[0] == '.')
                    continue;

                ZeroMemory(TempFileName, MaxLength);

                for(WritePos = 0; WritePos < MaxLength; WritePos++)
                {
                    if(c_file.name[WritePos] == '.')
                        break;

                    TempFileName[WritePos] = c_file.name[WritePos];
                }
            }

            SavedNewFileNr++;
        }

        _findclose(hFile);

        if(WritePos > 0)
        {
            ZeroMemory(g_AnimationPoseFileName, 2*MaxLength);
            ZeroMemory(g_AnimationPoseName, MaxLength);

            sprintf(g_AnimationPoseFileName, "%s%s.txt", pDirectory,
                    TempFileName);

            strcpy(g_AnimationPoseName, TempFileName);

            // Schreibe-Position an das Namensende setzen:
            g_AnimationPoseNameWritePos = WritePos;
        }
        // Es konnte keine Datei mit dem Index g_NewAnimationPoseFileNr
        // gefunden werden. Daher wird der Index nun dekrementiert und
        // die Select_NewAnimationPose()-Funktion erneut aufgerufen:
        else
        {
            g_NewAnimationPoseFileNrLastFrame--;
            g_NewAnimationPoseFileNr--;

            if(g_NewAnimationPoseFileNr > 0)
                Select_NewAnimationPose(pDirectory);
        }
    }
}

Mit Hilfe der _findfirst()-Funktion wird zunächst getestet, ob der zu durchsuchende Ordner überhaupt existiert. Wenn das der Fall ist, werden alle Dateien innerhalb des Ordners nacheinander mit Hilfe der _findnext()-Funktion durchlaufen. Gespeichert werden die von beiden Funktionen ermittelten Datei-Informationen in der Strukturvariablen c_file vom Typ _finddata_t. Während des Schleifen-Durchlaufs lässt sich jeder gefundenen Datei eine eindeutige Dateinummer (SavedNewFileNr) zuordnen. Der Benutzer wählt seinerseits die zu ladende Datei über eine Dateinummer (g_NewAnimationPoseFileNr) aus. Wurde die vom Benutzer ausgewählte Datei gefunden
(SavedNewFileNr == g_NewAnimationPoseFileNr), dann wird der Dateiname ohne Endung in das g_AnimationPoseName- und der Dateiname samt Dateipfad in das g_AnimationPoseFileName-char-Array kopiert und die Funktion anschließend verlassen.