2012-05-04 13 views
8

momento de escribir este código para obtener nombre de archivo para guardar mi archivo:cómo guardar el archivo con GetSaveFileName en 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; 
} 

Pero la salida es:

the path is : H 

por qué? Estoy haciendo algo mal ?
Estoy usando Visual Studio 2008 en Windows 7.

+1

+1 para un ejemplo completo y una pregunta bien formulada. –

Respuesta

8

Esta línea:

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

debe utilizar la versión de carbón de ancho de printf.

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

+1 ganas ... esta vez. :) –

+1

Como el resto del código, incluido el valor 'lpstrFile', se basa en' _TCHAR', debe usar '_tprintf' en su lugar:' _tprintf (_T ("la ruta es:% s \ n"), ofn .lpstrFile); ' –

+2

-1 Este código sigue siendo peligroso porque el buffer es demasiado pequeño. –

8

La raíz del problema está en estas líneas:

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

Esto crea un buffer de caracteres MAX_PATH, pero indica a la función GetSaveFileName que se trata de un buffer de MAX_PATH amplia caracteres. Es probable que se bloquee (o pisotee silenciosamente la memoria) cuando alguien elige un nombre de ruta larga.

The giveaway is the cast. No mientas al compilador ni a las bibliotecas. No les gusta eso, y siempre obtendrán su venganza al final. Reemplace esas líneas con esto:

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

Ahora el nombre de archivo seleccionado se devolverá como una cadena de caracteres anchos. respuesta de Tony del león es correcta en ese que usted necesita utilizar wprintf en lugar de printf para imprimir cadenas de caracteres anchos:

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

Si necesita la cadena de caracteres de 8 bits en lugar de caracteres anchos, se puede utilizar WideCharToMultiByte . Pero me quedaría con las API de caracteres anchos en general.

Nunca lance a menos que sepa exactamente lo que hace y por qué es necesario en su caso particular.

-1

Ambos están equivocados, es un simple problema de puntero/pila C.

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

Esto confunde a arreglos y apuntadores, que declarar una matriz en la pila, pero luego cambia su dirección de memoria para apuntar a una cadena vacía en la sección de datos. En otras palabras, un desbordamiento de búfer.

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

Esto declara una matriz de caracteres en la pila e inicializa todos los elementos en el terminador nulo.

Espero que ayude!

+0

Las cadenas literales en el lado derecho de los inicializadores de matriz tienen un significado especial.La declaración 'char szFileName [MAX_PATH] =" "'; * no * crea un puntero Inicializa 'szFileName [0] a '\ 0'', es decir, el terminador nulo. –

Cuestiones relacionadas