CÓMO: Escribir una aplicación de Windows XP que almacene datos de usuarios y de aplicaciones en la ubicación correcta

Seleccione idioma Seleccione idioma
Id. de artículo: 310294 - Ver los productos a los que se aplica este artículo
Este artículo se publicó anteriormente con el número E310294
Expandir todo | Contraer todo

En esta página

Resumen

Las aplicaciones funcionan con dos tipos de documentos: los creados por el usuario y los creados por la aplicación. Las aplicaciones deben utilizar la función de shell SHGetFolderPath para recuperar ubicaciones válidas de carpeta donde almacenar datos específicos del usuario y de la aplicación. Esto es esencial para que las aplicaciones de Windows XP acepten varios usuarios que utilizan el mismo equipo y para permitir el cambio rápido de usuario.

En este artículo se describe cómo almacenar datos de usuario en el lugar correcto en los pasos siguientes:
  • Crear una aplicación Win32.
  • Agregar una opción Guardar como al menú Archivo.
  • Utilizar el cuadro de diálogo estándar Guardar archivo para guardar en la ubicación correcta de manera predeterminada.
  • Comprobar la ubicación correcta para guardar archivos.
  • Recordar la selección anterior del usuario.
  • Comprobar la selección anterior del usuario.
En los pasos siguientes se describe también dónde debe almacenar datos de aplicación y cómo asegurarse de que se almacenan en las ubicaciones apropiadas:
  • Clasificar datos de aplicación.
  • Almacenar datos de aplicación en la ubicación correcta.
  • Utilizar el Registro con cuidado.

Requisitos

En la lista siguiente se describen el hardware, el software, la infraestructura de red, las capacidades, el conocimiento y los Service Pack que se necesitan:
  • Windows XP Home Edition o Windows XP Professional
  • Visual Studio .NET o Visual Studio versión 6.0
  • Conocimientos previos del desarrollo de aplicaciones Win32

Crear una aplicación Win32

Inicie Visual Studio y cree una nueva aplicación Win32 denominada SavingData.
  • En Visual C++ 6.0, haga clic en Aplicación Win32 en la lista de tipos de proyecto disponibles y seleccione la opción Una típica aplicación "Hola a todos" dentro del Asistente para instalación de aplicaciones.
  • En Visual Studio .NET, haga clic en Proyectos de Visual C++ bajo Tipos de proyecto y, después, haga clic en Proyecto Win32 bajo Plantillas. Acepte la configuración predeterminada mostrada por el Asistente para instalación de aplicaciones.

Agregar una opción Guardar como al menú Archivo

  1. Haga clic en Vista de recursos y, después, haga doble clic en IDC_SAVINGDATA.
  2. Agregue una opción Guardar como al menú Archivo. Utilice IDM_FILE_SAVEAS como Id. del elemento de menú.
  3. Busque el procedimiento de ventana WndProc de la aplicación dentro de SavingData.cppm y agregue una nueva instrucción case dentro de la sección WM_COMMAND para procesar la opción de menú Guardar como. Llame a la función OnFileSaveAs, que creará en la próxima sección. Esta función no toma ningún parámetro.

    El código debe aparecer de la siguiente forma:
    case WM_COMMAND:
       wmId    = LOWORD(wParam);
       wmEvent = HIWORD(wParam);
       // Analizar las selecciones de menú.
       switch (wmId)
       {
       case IDM_ABOUT:
          DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
          break;
       case IDM_EXIT:
          DestroyWindow(hWnd);
          break;
       case IDM_FILE_SAVEAS:
          OnFileSaveAs();
          break;
       default:
          return DefWindowProc(hWnd, message, wParam, lParam);
       }
       break;

Utilizar el cuadro de diálogo estándar Guardar archivo para guardar en la ubicación correcta de manera predeterminada

Cuando un usuario muestra por primera vez el cuadro de diálogo Guardar archivo (o Abrir archivo) de una aplicación, el cuadro de diálogo debe señalar de manera predeterminada a la carpeta Mis documentos del usuario (o a una descendiente de ella, como Mis imágenes en el caso de datos de imágenes y Mi música en el caso de archivos de audio).

NOTA: nunca debe codificar una ruta de acceso dentro de la aplicación porque no se puede garantizar su ubicación física. Por ejemplo, un Administrador puede reubicar la carpeta Mis documentos en una ubicación de red.
  1. En la parte superior de SavingData.cpp, agregue las siguientes instrucciones include:
    #include <commdlg.h>   // for GetSaveFileName
    #include <shlobj.h>    // for SHGetFolderPath
  2. Agregue el prototipo siguiente para la función OnFileSaveAs:
    void OnFileSaveAs();
  3. Cree la nueva función OnFileSaveAs. Dentro de esta función, utilice la función SHGetFolderPath junto con el identificador CSIDL_MYPICTURES CSIDL para recuperar la ubicación correcta de la carpeta donde almacenar datos de imágenes. Pase esta ubicación de carpeta a la función GetSaveFileName para mostrar el cuadro de diálogo estándar Guardar archivo.

    El código debe aparecer de la siguiente forma:
    void OnFileSaveAs()
    {
       OPENFILENAME openFile;
       TCHAR szPath[MAX_PATH];
    
    // Inicializar estructura OPENFILENAME.
    ZeroMemory( &openFile, sizeof(OPENFILENAME) );
    openFile.lStructSize = sizeof(OPENFILENAME);
    // De manera predeterminada es Mis imágenes. Primero, obtener su ruta de acceso.
    if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_MYPICTURES, 
                                          NULL, 0, szPath ) ) )
    {
       // Configurar lpstrInitialDir como la ruta de acceso que SHGetFolderPath obtiene.
       // Esto hace que GetSaveFileName señale a la carpeta Mis imágenes.
          openFile.lpstrInitialDir = szPath;
    }
    // Mostrar el cuadro de diálogo estándar Guardar archivo, con la carpeta predeterminada Mis imágenes.
    if ( GetSaveFileName( &openFile ) == TRUE )
    {
          // El usuario hace clic en el botón Guardar.
       // Guardar el archivo
    }
    else
    {
       // El usuario cancela el cuadro de diálogo Guardar archivo.
    }
    }

Comprobar la ubicación correcta para guardar archivos

  1. Presione la tecla F5 para generar el proyecto.
  2. Ejecute la aplicación y haga clic en Guardar como en el menú Archivo.
  3. Compruebe que el cuadro de diálogo estándar Guardar archivo señala de manera predeterminada a la carpeta Mis imágenes, según especifica CSIDL_MYPICTURES.
  4. Haga clic en Cancelar para cerrar el cuadro de diálogo y cierre la aplicación.

Recordar la selección anterior del usuario

Para posteriores usos del cuadro de diálogo Guardar archivo (o Abrir archivo) se recomienda que señale de manera predeterminada a la ubicación seleccionada previamente por el usuario.

Si no especifica una ubicación de carpeta inicial dentro de la estructura OPENFILENAME, GetSaveFileName (y GetOpenFileName) mostrará el cuadro de diálogo estándar Guardar archivo o Abrir archivo, que señala a la carpeta Mis documentos. Además, si el usuario ha utilizado uno de estos cuadros de diálogo anteriormente y ha elegido una carpeta distinta de la predeterminada, estas funciones utilizan automáticamente de manera predeterminada la carpeta utilizada previamente.

Para permitir el procedimiento recomendado de dirigirse a una ubicación de carpeta determinada (como Mis imágenes) la primera vez que un usuario guarda o carga un archivo, y para señalar de manera predeterminada a la ubicación seleccionada previamente por el usuario, debe utilizar una variable booleana para hacer un seguimiento de si ésta es la primera vez que el usuario ha realizado la operación de guardar o de abrir.
  1. Cree una variable static BOOL llamada bFirstSave en la función OnFileSaveAs e inicialícela como TRUE.
  2. Modifique el código dentro de OnFileSaveAs para llamar a SHGetFolderPath y configurar el miembro lpstrInitialDir de la estructura OPENFILENAME, sólo si bFirstSave es TRUE.
  3. Si el usuario hace clic en Guardar en el cuadro de diálogo Guardar archivo, configure bFirstSave como FALSE.

    El código debe aparecer de la siguiente forma:
    void OnFileSaveAs()
    {
       OPENFILENAME openFile;
       TCHAR szPath[MAX_PATH];
       static BOOL bFirstSave = TRUE;
    
    // Inicializar estructura OPENFILENAME.
    ZeroMemory( &openFile, sizeof(OPENFILENAME) );
    openFile.lStructSize = sizeof(OPENFILENAME);
    // La primera vez que el usuario guarda un documento, utilizar de manera predeterminada Mis imágenes.
       if ( TRUE == bFirstSave )
    {
       if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_MYPICTURES,
                                             NULL, 0, szPath ) ) )
       {
             // Configurar lpstrInitialDir como la ruta de acceso obtenida por SHGetFolderPath.
             // Esto hace que GetSaveFileName señale a la carpeta Mis imágenes.
             openFile.lpstrInitialDir = szPath;
       }
    }
    // Mostrar el cuadro de diálogo estándar Guardar archivo, con la carpeta predeterminada Mis imágenes
    // o la ubicación seleccionada anteriormente por el usuario.
    if ( GetSaveFileName( &openFile ) == TRUE )
    {
       // El usuario hace clic en Guardar.
       // Guardar el archivo.
          bFirstSave = FALSE;
    }
    else
    {
          // El usuario cancela el cuadro de diálogo Guardar archivo.
    }
    }

Comprobar la selección anterior del usuario

  1. Genere el proyecto y ejecute la aplicación.
  2. En el menú Archivo, haga clic en Guardar como.
  3. Examine desde la carpeta Mis imágenes hasta la carpeta Mis documentos, seleccione un archivo y haga clic en Guardar.
  4. En el menú Archivo, haga clic de nuevo en Guardar como.
  5. Compruebe que el cuadro de diálogo utiliza de manera predeterminada la selección anterior (en este caso, Mis documentos).
  6. Haga clic en Cancelar para descartar el cuadro de diálogo y cierre la aplicación.
  7. Ejecute la aplicación y haga clic en Guardar como en el menú Archivo.
  8. Compruebe que el cuadro de diálogo vuelve de manera predeterminada a la carpeta Mis imágenes.
  9. Cierre el cuadro de diálogo y salga de la aplicación.

Clasificar datos de aplicación

No debe almacenar datos específicos de la aplicación (como archivos temporales, preferencias de usuario, archivos de configuración de aplicaciones, etc.) en la carpeta Mis documentos. En su lugar, utilice una ubicación apropiada del Registro de Windows (para datos que no superan los 64 kilobytes) o un archivo específico de la aplicación que se encuentra en una carpeta Datos de programa válida.

Es importante almacenar los datos de aplicación en la ubicación correcta para permitir que varias personas utilicen el mismo equipo sin dañar ni sobrescribir los datos y las configuraciones de los demás.

Con el fin de determinar la ubicación más apropiada para los datos de aplicación, utilice las categorías siguientes para clasificar los datos:
  • Para cada usuario (itinerante): Esta categoría describe los datos de aplicación específicos de un usuario determinado y que deben estar disponibles para el usuario a medida que éste cambie de equipo dentro de un dominio (por ejemplo, un diccionario personalizado). Tenga en cuenta que esta configuración no se aplica a las aplicaciones que no están diseñadas para ejecutarse en un entorno de dominios.
  • Para cada usuario (no itinerante): Esta categoría describe los datos de aplicación que son específicos de un usuario determinado pero que sólo se aplican a un equipo (por ejemplo, una resolución de monitor especificada por el usuario).
  • Para cada equipo (no específico de usuario y no itinerante): Esta categoría describe los datos de aplicación que se aplican a todos los usuarios y a un equipo determinado (por ejemplo, un diccionario de aplicación, un archivo de registro o un archivo temporal).

Almacenar datos de aplicación en la ubicación correcta

Utilice la función SHGetFolderPath para recuperar la carpeta Datos de programa correcta. No almacene los datos de aplicación directamente en esta carpeta. En su lugar, utilice la función PathAppend para anexar una subcarpeta a la ruta de acceso devuelta por SHGetFolderPath. Asegúrese de utilizar la convención siguiente:
Nombre de compañía\Nombre de producto\Versión del producto
Por ejemplo, la ruta de acceso completa resultante puede aparecer de la manera siguiente:
\Documentos y configuraciones\Todos los usuarios\Datos de programa\Mi compañía\Mi producto\1.0
Para encontrar la carpeta Datos de programa correcta, pase el valor CSIDL apropiado según la categoría de los datos de aplicación.
  • Para datos de cada usuario (itinerante), utilice el valor CSIDL_APPDATA. Esto señala de manera predeterminada a la ruta de acceso siguiente:
    \Documentos y configuraciones\< Nombre de usuario >\Datos de programa
  • Para datos de cada usuario (no itinerante), utilice el valor CSIDL_LOCAL_APPDATA. Esto señala de manera predeterminada a la ruta de acceso siguiente:
    \Documentos y configuraciones\< Nombre de usuario >\Configuración local\Datos de programa
  • Para datos de cada equipo (no específicos del usuario y no itinerante), utilice el valor CSIDL_COMMON_APPDATA. Esto señala de manera predeterminada a la ruta de acceso siguiente:
    \Documentos y configuraciones\Todos los usuarios\Datos de programa
En el fragmento de código siguiente se muestra cómo abrir un archivo de registro temporal, que se encuentra bajo CSIDL_COMMON_APPDATA:
void CreateTemporaryFile()
{
   TCHAR szPath[MAX_PATH];
   // Obtener la ruta de acceso para cada equipo, con datos no específicos del usuario y no itinerantes.
   if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_COMMON_APPDATA,
                                    NULL, 0, szPath ) ) )
   {
      TCHAR szTempFileName[MAX_PATH];
      // Anexar ruta de acceso específica del producto.
      PathAppend( szPath, "\\Mi compañía\\Mi producto\\1.0\\" );
      // Generar un nombre de archivo temporal dentro de esta carpeta.
      if (GetTempFileName( szPath,
                           "PRE",
                           0,
                           szTempFileName ) != 0 )
      {
         HANDLE hFile = NULL;
         // Abrir el archivo.
         if (( hFile = CreateFile( szTempFileName,
                                     GENERIC_WRITE,
                                     0,
                                     NULL,
                                     CREATE_ALWAYS,
                                     FILE_ATTRIBUTE_NORMAL,
                                     NULL )) != INVALID_HANDLE_VALUE )
         {
            // Escribir datos temporales (se ha omitido código).
            CloseHandle( hFile );
         }
      }
   }
}

Utilizar el Registro con cuidado

ADVERTENCIA: si utiliza incorrectamente el Editor del Registro puede tener serios problemas que requerirán volver a instalar el sistema operativo. Microsoft no puede garantizar la solución de los problemas resultantes del uso incorrecto del Editor del Registro. Utilice el Editor del Registro bajo su responsabilidad.

Para obtener información acerca de cómo modificar el Registro, consulte el tema de Ayuda "Cambiar claves y valores" en el Editor del Registro (Regedit.exe) o los temas "Agregar y eliminar información del Registro" y "Modificar información del Registro" en Regedt32.exe. Tenga en cuenta que debe hacer una copia de seguridad del Registro antes de modificarlo. Si está utilizando Windows NT o Windows 2000, también deberá actualizar el Disco de reparación de emergencia (ERD).

También puede utilizar el Registro para almacenar pequeñas cantidades de datos de la aplicación. En el caso de datos que tengan más de 64 kilobytes (KB), debe utilizar una carpeta Datos de programa. Tenga en cuenta lo siguiente cuando utilice el Registro para almacenar datos de aplicación:
  • Para pequeñas cantidades de datos de usuario, utilice la clave HKEY_CURRENT_USER (HKCU) del Registro.
  • Para pequeñas cantidades de datos de equipo, utilice la clave HKEY_LOCAL_MACHINE (HKLM) del Registro. La aplicación no debe escribir en HKLM en tiempo de ejecución ya que, de manera predeterminada, los usuarios que no son administradores sólo tienen acceso de sólo lectura al árbol HKLM.
  • En el momento de la instalación la aplicación no debe almacenar más de un total de 128 KB entre HKCU y HKLM.
  • Los componentes del Modelo de objetos componentes (COM) se registran bajo la clave HKEY_CLASSES_ROOT (HKCR) del Registro. El máximo de 128 KB no incluye HKCR.
  • Cuando escribe en HKLM o en HKCU, debe crear claves para el nombre de compañía, el nombre de producto y el número de versión del producto, de la manera siguiente:
    HKLM\Software\Nombre de compañía\Nombre de producto\Versión del producto
    HKCU\Software\Nombre de compañía\Nombre de producto\Versión del producto
  • Utilice las funciones del Registro (como RegCreateKeyEx y RegSetValueEx) para leer y escribir entradas del Registro.

Solucionar problemas

  • Para asegurarse de que las aplicaciones se ejecutan en versiones anteriores de Windows además de en Windows XP, establezca siempre un vínculo a la implementación SHGetFolderPath en Shfolder.dll. Aunque Windows XP incluye SHGetFolderPath en Shell32.dll, puede que las versiones anteriores de Windows no admitan la función dentro de esta biblioteca de vínculos dinámicos (DLL).
  • Shfolder.dll es un componente redistribuible y puede distribuirse con las aplicaciones.
  • No almacene rutas completas en la carpeta Mis documentos (u otras carpetas del sistema) dentro de un sitio específico de la aplicación, como una lista de los archivos utilizados más recientemente porque un usuario o un Administrador puede reubicar estas carpetas entre los usos sucesivos de su aplicación.

REFERENCIAS

Para obtener más información acerca del conjunto completo de carpetas que SHGetFolderPath puede identificar, consulte la siguiente documentación del Kit de desarrollo de software (SDK) de la plataforma de Microsoft:
CSIDL Values
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/Shell/Functions/csidl.asp
Para obtener más información acerca de la programación de shell en general, consulte el sitio Web de MSDN:
Shell Programmers Guide
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/Shell/shell_intro.asp
Para obtener más información general acerca de Visual C++ .NET, visite el siguiente grupo de noticias Usenet:
Microsoft.public.dotnet.languages.vc
Visite el centro de soporte técnico de Visual C++ .NET en:
Visual C++ .NET (2002) Support Center

Propiedades

Id. de artículo: 310294 - Última revisión: jueves, 31 de enero de 2002 - Versión: 1.0
La información de este artículo se refiere a:
  • Microsoft Visual C++ .NET 2002 Standard
Palabras clave: 
kbhowto kbhowtomaster kbnewsgrouplink KB310294

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com