[C con Clase] common dialog y punteros.

Salvador Pozo salvador en conclase.net
Lun Abr 22 15:55:14 CEST 2013


Hola:

Como siempre que se trabaje con parámetros de tipo puntero, es muy importante prestar atención a posibles desbordamientos y fugas de memoria.

Lo de la variable estática a mi tampoco me convence, sólo lo mencioné como posible solución, pero tampoco sería mi primera opción.

En cuanto a cómo has resuelto la función, tengo algunas pegas.

Por ejemplo, si el valor del puntero a la cadena no va a modificarse, como de hecho así es, no tiene sentido pasar un puntero doble. Puedes usar un puntero sencillo (char*).

Si se asume que el tamaño de la cadena pasada como parámetro es lo bastante grande, puedes eliminar la variable local szFile:

----8<------

    char nombre[256];

    OpenFile((char*)nombre);
...

bool OpenFile(char * szFileName, int nSizeBuffer )
{
    OPENFILENAME ofn;       // common dialog box structure
    HWND hwnd = NULL;       // owner window

    // Initialize OPENFILENAME
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFile = (LPTSTR)szFileName; // Cadena pasada como parámetro
    //
    // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
    // use the contents of szFile to initialize itself.
    //
    ofn.lpstrFile[0] = '\0';
    ofn.nMaxFile = nSizeBuffer;  // Tamaño indicado en parámetro
    ofn.lpstrFilter = "Text\0*.TXT\0All\0*.*\0";
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    // Display the Open dialog box.

    if (GetOpenFileName(&ofn)==TRUE)
    {
        return true;
    }
    else
    {
        return false;
    }
}
----8<------

Para evitar el segundo parámetro hay un pequeño truco que a veces se usa también en el API, y es pasar la longitud de la cadena como primer valor de la propia cadena:

----8<------
char nombre[256];
*(int*)nombre = 256;


...

bool OpenFile(char * szFileName )
{
    OPENFILENAME ofn;       // common dialog box structure
    HWND hwnd = NULL;       // owner window

    // Initialize OPENFILENAME
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFile = (LPTSTR)szFileName;
    ofn.nMaxFile = *(int*)szFileName; // Longitud del buffer
    //
    // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
    // use the contents of szFile to initialize itself.
    //
    ofn.lpstrFile[0] = '\0';
    ofn.lpstrFilter = "Text\0*.TXT\0All\0*.*\0";
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    // Display the Open dialog box.

    if (GetOpenFileName(&ofn)==TRUE)
    {
        return true;
    }
    else
    {
        return false;
    }
}
----8<------

En cuanto a lo de dejar el tamaño del buffer como fijo creo que no tienes muchas opciones, la función GetOpenFileName retornará false si no hay espacio suficiente para almacenar el nombre del fichero, de modo que tienes que asegurarte de que el tamaño sea lo bastante grande antes de llamar a la función.

Hasta pronto.

-- 
Salvador Pozo (Administrador)
mailto:salvador en conclase.net


Más información sobre la lista de distribución Cconclase