| Ver tema anterior :: Ver siguiente tema | | Autor | Mensaje |
|---|
eagleoneraptor

Registrado: 20 May 2008 Mensajes: 187 Ubicación: Buenos Aires(Argentina)
| Publicado: 03/06/2008 12:36 pm | | | Título: OPENFILENAME - OFN_ALLOWMULTISELECT |
| Hola, estoy intentando usar la función GetOpenFileName y la estructura OPENFILENAME con el flag OFN_ALLOWMULTISELECT, esto es para seleccionar muchos archivos de una sola vez.
La cadena almacenada es el camino al conjunto de archivos seleccionados y el nombre de cada archivo separado por \0. Pude hacer una función que separa esto correctamente, pero no me convense del todo:
| Código: | void GetOneFile(char *stFileName,char *stOne,int nFile) { int i; strcpy(stOne,stFileName); if(nFile>0){ for(i=1;i<=nFile;i++){ stFileName+=strlen(stFileName)+1; } strcat(stOne,"\\"); strcat(stOne,stFileName); } else stOne=NULL; } |
Seguro que hay una forma estandar de hacerlo y quisiera saberla, otra cosa, yo uso para almacenar la cadena una variable de este tipo:
char stCadena[MAX_PATH];
y cuando selecciono archivos de mas, guarda cualquier cosa en la cadena ya que supera su capacidad.
Si me pueden ayudar se los agradecería.
Saludos! _________________ "Aquel que hace una bestia de si mismo se libra del dolor de ser un hombre". Dr. Johnson |
| | Volver arriba | |  | untio

Registrado: 17 Sep 2008 Mensajes: 380 Ubicación: MICA S.A.
| Publicado: 06/08/2009 7:52 am | | | Título: |
| Hola, No sé nada sobre tu nivel de inglés. Cuando deseas que se muestre el diálogo estándar para abrir archivos has de llenar la estructura OPENFILENAME. Lee todo lo que sigue sobre uno de los campos de ella:
lpstrFile
Pointer to a buffer that contains a file name used to initialize the File Name edit control. The first character of this buffer must be NULL if initialization is not necessary. When the GetOpenFileName or GetSaveFileName function returns successfully, this buffer contains the drive designator, path, file name, and extension of the selected file. If the OFN_ALLOWMULTISELECT flag is set and the user selects multiple files, the buffer contains the current directory followed by the file names of the selected files. For Explorer-style dialog boxes, the directory and file name strings are NULL separated, with an extra NULL character after the last file name. For old-style dialog boxes, the strings are space separated and the function uses short file names for file names with spaces. You can use the FindFirstFile function to convert between long and short file names. If the user selects only one file, the lpstrFile string does not have a separator between the path and file name.
If the buffer is too small, the function returns FALSE and the CommDlgExtendedError function returns FNERR_BUFFERTOOSMALL. In this case, the first two bytes of the lpstrFile buffer contain the required size, in bytes or characters.
Espero que sea útil. |
| | Volver arriba | |  | eagleoneraptor

Registrado: 20 May 2008 Mensajes: 187 Ubicación: Buenos Aires(Argentina)
| Publicado: 06/08/2009 11:31 am | | | Título: |
| Gracias por responder.
Pero mi pregunta era si habia alguna función de la API para separar los nombres de archivo entre los NULL, mas bien, la función que puse alli, mas optimizada.
Lo de FNERR_BUFFERTOOSMALL si explica mi segunda cuestión.
Un Saludo! _________________ "Aquel que hace una bestia de si mismo se libra del dolor de ser un hombre". Dr. Johnson |
| | Volver arriba | |  | | rir3760

Registrado: 01 Oct 2004 Mensajes: 7516 Ubicación: Mexico
| Publicado: 06/08/2009 5:37 pm | | | Título: |
| Tres detalles que no me gustan de esa funcion:
1) Primero copias y luego verificas, esto es malo (mas bien ineficiente) porque la copia solo es necesaria si el valor de "nFile" es mayor que cero.
2) Puedes sustituir las tres llamadas a funcion (strcpy + strcat) con una sola llamada a sprintf.
3) El programa no producira los resultados esperados si el indice esta fuera del rango valido.
Una version mas solida es:
| Código: | void GetOneFile(char *stFileName, char *stOne, int nFile) { stOne = NULL; /* predeterminado en caso de error */ if (nFile > 0){ char *dir; int i; dir = stFileName; for (i = 0; i < nFile && *stFileName != '\0'; i++) stFileName += strlen(stFileName) + 1; if (*stFileName != '\0') sprintf(stOne, "%s\\%s", dir, stFileName); } } |
Pensandolo un poco una mejor opcion seria obtener indices a cada una de las cadenas una vez obtenidas estas mediante la mentada funcion.
Un saludo _________________ C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly. -- Kernighan & Ritchie, The C programming language |
| | Volver arriba | |  | untio

Registrado: 17 Sep 2008 Mensajes: 380 Ubicación: MICA S.A.
| Publicado: 13/01/2010 8:12 am | | | Título: |
| Hola, Curiosamente, hace unas semanas me encontré con el problema de programar un cuadro de apertura de múltiples archivos (que podían ser muchísimos). Aquí sigue mi código:
| Código: | ////////////////////////////////////////////////////////////////////////////// static TCHAR * fichs; ////////////////////////////////////////////////////////////////////////////// static INT_PTR AnnadirFilesALista(HWND hwnd, UINT listaid, UINT otralistaid) { OPENFILENAME ofn; INT pos = 0; TCHAR ruta[MAX_PATH * 2]; TCHAR completo[MAX_PATH * 2]; fichs = (TCHAR *) malloc(sizeof(TCHAR) * 8); if(fichs == NULL) MostrarError(ecErrorDeMemoria, TEXT(__FILE__), __LINE__); fichs[0] = TEXT('\0'); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hwnd; #ifdef CASTELLANO ofn.lpstrFilter = TEXT("Todos los ficheros\0*.*\0\0"); #endif #ifdef ENGLISH ofn.lpstrFilter = TEXT("All files\0*.*\0\0"); #endif ofn.lpstrCustomFilter = NULL; ofn.nFilterIndex = 0; ofn.lpstrFile = fichs; ofn.nMaxFile = 3; ofn.lpstrFileTitle = NULL; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = TEXT(SZSELECTFILES); ofn.lpfnHook = MiOFNHookProc; ofn.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_DONTADDTORECENT | OFN_NODEREFERENCELINKS | OFN_NONETWORKBUTTON; ofn.lpstrDefExt = NULL; if(GetOpenFileName(&ofn) == FALSE) { { free(fichs); return TRUE; } } _tcscpy(ruta, TEXT("\\\\?\\")); _tcscat(ruta, &fichs[pos]); if(!(GetFileAttributes(ruta) & FILE_ATTRIBUTE_DIRECTORY)) { AnnadirItemALaLista(hwnd, listaid, otralistaid, &ruta[4]); free(fichs); return TRUE; } if(ruta[_tcslen(ruta) - 1] != TEXT('\\')) _tcscat(ruta, TEXT("\\")); while(fichs[pos] != TEXT('\0')) ++pos; ++pos; while(fichs[pos] != TEXT('\0')) { _tcscpy(completo, ruta); _tcscat(completo, &fichs[pos]); if(GetFileAttributes(completo) != INVALID_FILE_ATTRIBUTES) { AnnadirItemALaLista(hwnd, listaid, otralistaid, &completo[4]); } while(fichs[pos] != TEXT('\0')) ++pos; ++pos; } free(fichs); return TRUE; } ///////////////////////////////////////////////////////////////// UINT_PTR CALLBACK MiOFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { NMHDR *phd; OFNOTIFY * pon; UINT cucu; TCHAR buf[4]; OPENFILENAME * ofn; if(uiMsg != WM_NOTIFY) { return 0; } phd = (NMHDR *) lParam; if(phd->code != CDN_SELCHANGE) { return 0; } pon = (OFNOTIFY *) lParam; cucu = SendMessage(GetParent(hdlg), CDM_GETSPEC, 2, (LPARAM) buf); fichs = (TCHAR *) realloc(fichs, (MIMAXPATH * sizeof(TCHAR)) + (sizeof(TCHAR) * cucu) + 44 ); if(fichs == NULL) MostrarError(ecErrorDeMemoria, TEXT(__FILE__), __LINE__); ofn = (OPENFILENAME *) pon->lpOFN; ofn->lpstrFile = fichs; ofn->nMaxFile = (MIMAXPATH) + cucu + 22; NOUSADO(wParam); return 0; }
|
Al sistema le indicas una función de retrollamada (que es llamada por el sistema) que es notificada de los cambios en la selección. Un problema que notarás si usas este código es que el sistema sólo copia un cierto número de caracteres en el buffer. Cuando seleccionas demasiados archivos, el sistema corta en un cierto límite. Por la red he leído que es un bug de windows. Al menos en mi win2k sucede. Tal vez esté solucionado en sistemas más actuales. Sólo comentarte acerca de mi código que en mis proyectos redefino MAX_PATH como 2600 y MIMAXPATH la defino como 2600. TCHAR es igual a char si se no se ha definido unicode y wchar si se ha hecho. Las funciones del tipo _tcscpy están definidas en tchar.h. Cambia a strcpy si se no se ha definido unicode y a la versión para wide chars si se ha hecho. En cuanto a la cadena "\\\\?\\", la uso para poder trabajar con rutas de mas de MAX_PATH caracteres. O sea rutas de más de 260 caracteres. El tema es que windows sólo permite trabajar con rutas de hasta 260 caracteres, pero ntfs permite rutas de 32.000 y pico caracteres. Algunas funciones que trabajan con rutas permiten hablar directamente con el sistema de archivos anteponiendo a la ruta la cadena \\?\. Lo malo es que unas lo permiten y otras no. TEXT transforma el argumento en unicode si éste se ha definido, o en ansi si no. __FILE__ devuelve el nombre del archivo fuente donde se define. __LINE__ devuelve el número de línea donde se define. Otro tema es que cuando se devuelve un solo archivo se hace como su ruta. Cuando se devuelve más de uno, primero se devuelve la carpeta y luego los nombres de los archivos sin la carpeta. Por lo demás, espero que sepáis perdonar mis errores.
Espero que sea útil. |
| | Volver arriba | |  | | |
| No puede crear mensajes No puede responder temas No puede editar sus mensajes No puede borrar sus mensajes No puede votar en encuestas
|
|
| |