[C con Clase] common dialog y punteros.

Hugo García hgc2204 en gmail.com
Mar Abr 23 17:09:10 CEST 2013


Hola Salvador,

Muy útiles tus consejos, los he probado todos y creo que aunque no me guste
tratar con arrays de caracteres (el c# y el tipo string me ha dejado
vendido a la hora de pelear con esto sin framework xD) voy a usarlos casi
todos.

El tema de usar un doble puntero, básicamente era por desconocimiento de la
materia y por mayor comodidad (comodidad mía  fruto de la falta de habito),
ya que así no tenía que declarar array de caracteres, pero si lo piensas
detenidamente da lo mismo, porque hay que indicar un tamaño de buffer para
la cadena, por lo que tienes razón, no merece la pena usar el doble puntero.

En cuanto al resultado final, te pongo como la he dejado.

bool OpenFile(char * szFileName, int nSizeBuffer, char * szFilter, HWND
hOwnerWindow)
{
    OPENFILENAME ofn;       // common dialog box structure

    // Initialize OPENFILENAME
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hOwnerWindow;       // owner window
    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;         // buffer for file name (szFileName
array size)
    ofn.lpstrFilter = szFilter;
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    // Display the Open dialog box.
    return GetOpenFileName(&ofn);
}

Al final paso más de un parámetro, pero es por "universalizar la función",
y meterla dentro de un .h que sea usable y entendible facilmente por otra
persona que no sea yo (aunque luego este propósito caiga en saco roto, que
espero que no xD).

He estado apunto de usar el truco que me comentas de inicializar la cadena
con el tamaño del array, pero por el motivo que te comento antes lo he
dejado que se pase como parámetro, creo que queda mucho más claro (mi
opinión xD), de cara a un usuario que sepa programar pero sin que tenga
grandes conocimientos de la api

Asi que nada, gracias por todo de nuevo, estamos en contacto.

Un saludo.



El 22 de abril de 2013 15:55, Salvador Pozo <salvador en conclase.net>escribió:

> 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
> _______________________________________________
> Lista de correo Cconclase Cconclase en listas.conclase.net
> http://listas.conclase.net/mailman/listinfo/cconclase_listas.conclase.net
> Bajas: http://listas.conclase.net/index.php?gid=2&mnu=FAQ
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.conclase.net/pipermail/cconclase_listas.conclase.net/attachments/20130423/724adbd4/attachment.html>


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