2016-07-11 3 views
0

Dies ist eine Funktion, um eine Datei-Dialog in Windows zu öffnen und eine Zeichenfolge mit dem Dateinamen zurück:Wie eine Zeichenfolge aus GetOpenFileNameA zurückzukehren

#include <windows.h> 
#include <commdlg.h> 
#include <string.h> 
char* openFileDlg(char FileTypes[]); 
char* openFileDlg(char FileTypes[]){ 
    OPENFILENAME ofn; 
    char szFile[260]; 
    HWND hwnd; 
    HANDLE hf; 
    ZeroMemory(&ofn, sizeof(ofn)); 
    ofn.lStructSize = sizeof(ofn); 
    ofn.hwndOwner = hwnd; 
    ofn.lpstrFile = szFile; 
    ofn.lpstrFile[0] = '\0'; 
    ofn.nMaxFile = sizeof(szFile); 
    strcpy(ofn.lpstrFilter,FileTypes); 
    ofn.nFilterIndex = 1; 
    ofn.lpstrFileTitle = NULL; 
    ofn.nMaxFileTitle = 0; 
    ofn.lpstrInitialDir = NULL; 
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 
    if(GetOpenFileNameA(&ofn)){ 
     char *toReturn; 
     sprintf(toReturn,"%s",ofn.lpstrFile); 
     return toReturn; 
    } 
    else{ 
     return NULL; 
    } 
} 

Wenn ich diese Funktion aufrufen und eine Datei öffnen, wird der Prozess beendet und gibt den Wert 3 zurück (was bedeutet, dass ein Fehler vorliegt). Wie kann ich dies tun, dass diese Funktion eine Zeichenfolge mit dem Pfad der ausgewählten Datei zurückgibt?

Edit: Ich habe meinen Code dies geändert und es funktioniert immer noch nicht:

#include <windows.h> 
#include <commdlg.h> 
#include <string.h> 
void openFileDlg(char *toReturn[],char FileTypes[]); 
void openFileDlg(char *toReturn[],char FileTypes[]){ 
    OPENFILENAME ofn; 
    /* 
    Code for the settings of the GetOpenFileNameA, irrelevant in this question. 
    If you really need to know what's here, look at the code above. 
    */ 
    if(GetOpenFileNameA(&ofn)){ 
     strcpy(*toReturn,ofn.lpstrFile); 
    } 
    else{ 
     sprintf(*toReturn,""); 
    } 
} 

Ich soll auch sagen, dass, wenn ich die Box-Schaltfläche in der Datei-Dialog Abbrechen drücken, anstatt eine der Auswahl Datei, es funktioniert gut. Nach einigen Tests habe ich festgestellt, dass es die Zeile strcpy(*toReturn,ofn.lpstrFile); ist, die den Fehler verursacht.

+0

Wenn GetOpenFileNameA() macht das Programm beenden, dann müssen Sie das Gerät reparieren lassen. Beginnen Sie mit den benutzerdefinierten Shell-Erweiterungen, fragen Sie nach Hilfe auf superuser.com –

+0

strcpy (ofn.lpstrFilter, FileTypes); Hier versuchen Sie, auf Nulladresse zu schreiben, aber es gibt viele weitere Fehler –

+0

'ofn.hwndOwner = hwnd;' hwnd ist nicht initialisiert, tun Sie nur 'ofn.hwndOwner = NULL;'. – Sergio

Antwort

5

Die Zeigervariablen toReturn nicht überall darauf, sie in irgendeiner Weise verwenden, ohne es zu initialisieren (dh so dass es irgendwo gültig und groß genug, um Punkt) auf undefiniertes Verhalten führt

Sie haben zwei Lösungen wirklich:

  1. Speicher dynamisch zuweisen und einen Zeiger darauf zurückgeben. Dies erfordert natürlich, dass der Anrufer den Speicher freigibt, wenn er damit fertig ist.

  2. Lassen Sie die Funktion zwei weitere Argumente nehmen: Ein Zeiger auf einen Puffer und die Länge des Puffers. Kopieren Sie dann die Zeichenfolge in diesen Puffer, und geben Sie einen booleschen Erfolgs-/Fehlerstatus "Wahr" oder "Falsch" zurück.

Ich empfehle Lösung Nummer zwei.

auf einer nicht verwandte Notiz, gibt es keine Notwendigkeit, die teure sprintf Funktion in Ihrem Fall zu verwenden, ein einfaches strcpy (oder strncpy, wenn Sie mit der zweiten Lösung gehen) zu tun.

Sie müssen auch in beiden Fällen daran erinnern, dass Strings in C eine tatsächliche Länge von einem mehr als z. strlen Berichte, für die Beendigung '\0' Zeichen.

1

Sie haben keinen Speicher für Ihren Rückgabewert reserviert. Wenn Sie die Länge von ofn.lpstrFile wissen könnten Sie dies tun:

char *toReturn = malloc((sizeOfLpstrFile + 1) * sizeof(char)) ; 
    sprintf(toReturn,"%s",ofn.lpstrFile); 
    return toReturn; 

Noch halte ich dies eine schlechte Idee, weil die aufrufende Funktion muss den Speicher frei, die nicht offensichtlich von der Schnittstelle ist.

3

Im Allgemeinen, wenn Sie eine Zeichenfolge in C zurückkehren wollen, ich eine der folgenden Methoden verwenden würde:

1) in einem String-Puffer übergeben für die Methode zu schreiben:

int openFileDlg(char FileTypes[], char* toReturn, int bufLen) { 
    /* ... */ 
    snprintf(toReturn, bufLen, /* what you want to print */); 
    return ERROR; // status-code 
} 

/* ... */ 

char errorBuf[80]; 
int result; 

result = openFileDlg(..., errorBuf, sizeof(errorBuf)); 

2) Speicher zuweisen, erwarten Anrufer davon zu befreien:

char* openFileDlg(char FileTypes[]) { 
    /* ... */ 
    char *toReturn = malloc(/* big enough */); 
    sprintf(toReturn, /* what you want to print */); 
    return toReturn; 
} 

/* ... */ 
char* error = openFileDlg(...); 
if (error) { 
    /* ... */ 
    free(error); 
} 

persönlich, würde ich (1) bevorzugen, weil es sicherer ist.Option (2) ist für die API der Funktion angenehmer, birgt jedoch das Risiko von Speicherverlusten, wenn Sie vergessen, den zurückgegebenen Puffer freizugeben. In einem größeren Projekt (insbesondere mit mehreren daran arbeitenden Personen) ist dies ein sehr reales Risiko.

(Ich weiß, das ist so ziemlich das gleiche wie Joachim Antwort, aber seine ging auf, als ich mein schrieb)

Verwandte Themen