2012-05-04 15 views
8

piszę ten kod, aby uzyskać nazwę, aby zapisać mój plik:jak zapisać plik z GetSaveFileName w win32?

#include "stdafx.h" 
#include <windows.h> 


int _tmain(int argc, _TCHAR* argv[]) 
{    
    OPENFILENAME ofn; 

    char szFileName[MAX_PATH] = ""; 

    ZeroMemory(&ofn, sizeof(ofn)); 

    ofn.lStructSize = sizeof(ofn); 
    ofn.hwndOwner = NULL; 
    ofn.lpstrFilter = (LPCWSTR)L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"; 
    ofn.lpstrFile = (LPWSTR)szFileName; 
    ofn.nMaxFile = MAX_PATH; 
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; 
    ofn.lpstrDefExt = (LPCWSTR)L"txt"; 

    GetSaveFileName(&ofn); 
    printf("the path is : %s\n", ofn.lpstrFile); 
    getchar(); 
    return 0; 
} 

ale wyjście jest:

the path is : H 

dlaczego? Czy robię coś źle ?
Używam Visual Studio 2008 na Windows 7.

+1

+1 za kompletny przykład i dobrze sformułowane pytanie. –

Odpowiedz

8

Linia:

printf("the path is : %s\n", ofn.lpstrFile); 

należy użyć wersji szerokiej char printf.

wprintf(L"the path is : %s\n", ofn.lpstrFile); 
+1

+1 wygrasz ... tym razem. :) –

+1

Ponieważ reszta kodu, w tym wartość 'lpstrFile', oparta jest na' _TCHAR', powinieneś użyć '_tprintf' zamiast:' _tprintf (_T ("ścieżka jest:% s \ n"), ofn .lpstrFile); ' –

+2

-1 Ten kod jest nadal niebezpieczny, ponieważ bufor jest za mały. –

8

Problem główny jest w tych liniach:

char szFileName[MAX_PATH] = ""; 
... 
ofn.lpstrFile = (LPWSTR)szFileName; 
ofn.nMaxFile = MAX_PATH; 

ta tworzy bufor znaków MAX_PATH, ale opowiada GetSaveFileName funkcję, że jest to bufor MAX_PATH szeroki znaków. Może to spowodować awarię (lub po cichu zniszczyć pamięć), gdy ktoś wybierze długą nazwę ścieżki.

Gratisów jest obsada. Nie okłamuj kompilatora ani bibliotek. Oni tego nie lubią i zawsze zemszczą się w końcu. Zamień te linie na:

WCHAR szFileName[MAX_PATH] = L""; 
... 
ofn.lpstrFile = szFileName; // no cast needed 
ofn.nMaxFile = MAX_PATH; 

Teraz wybrana nazwa pliku zostanie zwrócona jako ciąg szerokich znaków. Odpowiedź Tony Lwia ma rację, że trzeba użyć wprintf zamiast printf do wydrukowania ciągów szerokich znaków:

wprintf(L"the path is : %s\n", ofn.lpstrFile); // though I'd use szFileName at this point 

Jeśli potrzebujesz ciąg w 8-bitowych znaków zamiast szerokich znaków, można użyć WideCharToMultiByte . Ale po prostu trzymałbym się ogólnie API o szerokich znakach.

Nigdy nie rzucaj, chyba że wiesz dokładnie, co robi i dlaczego jest to konieczne w twoim przypadku.

-1

Obaj jesteście w błędzie, to prosty problem ze wskaźnikiem C/stosem.

// WRONG: 
char szFileName[MAX_PATH] = ""; 

To dezorientuje tablice i wskaźniki, zadeklarować tablicę na stosie, ale następnie zmienić jego adres w pamięci, aby wskazać na pustym ciągiem w sekcji danych. Innymi słowy, przepełnienie bufora.

// RIGHT: 
char szFileName[MAX_PATH]; 
ZeroMemory(szFileName, MAX_PATH); 

Deklaruje tablicę znaków na stosie i inicjalizuje wszystkie elementy na wartość zerową.

Nadzieję, że pomaga!

+0

Dosłowne łańcuchy po prawej stronie inicjalizatorów macierzy mają specjalne znaczenie. –

Powiązane problemy