???? ID: 310294 - ????? ???????: 03 ?????? 2010 - ??????: 2.0

?????????? ?? ????????? ???? ????? C++ ?? ????? ?? ??? ????? ?? ???????? ???? ?? Windows XP ????????? ????? ?? ??? ???? ????

?????? ??????This article applies to a different operating system than the one you are using. Article content that may not be relevant to you is disabled.
???????????? ???? ??? ????????? ?? ???? ??????? ???? ?? ???? ??? ??????? ??.. ????????? ???? ?? ???? ????????? ?? ??????? ???? ?? ???? ???? ??? ?? ?? ???? ??.. ????????? ???? ?? ??? ?????? ??? ?? ???? ????????? ?? ???????????? ???? ??? ??.. ????????? ?? ??? ?? ????, ???????????? ????, ?? ??????? ???? ?? ???? ??? ???? ????? ?? ???, ????? ???? ?????? ?? ????? ?? ???? ?? Microsoft ???????? ??? ?????::
322756  (http://support.microsoft.com/kb/322756/ ) ??? ?? ???? ?? Windows ??? ????????? ?? ???????????? ???? ????
???:Microsoft Visual C++ .NET 2002, Microsoft Visual C++ .NET 2003, Microsoft Visual C++ 2005, ?? Microsoft Visual C++ 2008 Microsoft .NET Framework ?????? ??? ?? ??? ?? ???????? ???? ?? ????????? ??? Microsoft Windows ??? ???? ?? ??? ??????? ?? ???? ??? ?? ?? ??????? ???? ????????? ????? C++ ??? ?? ??? ???? ???? ??

?? ????? ??

??? ?? ??????? ???? | ??? ?? ??????? ????

??????

????????? ??????????? ?? ?? ?????? ?? ??? ?????: ?????????? ????? ?? ?? ?? ?? ?? ?? ????????? ????? ??? ???? ????????? ?? ????? ???? ?????SHGetFolderPath??? ?????? ?????????? ?? ????????? ?? ??? ??????? ?? ?? ???? ?? ???????? ???? ?? ??? ????? ?????? ????? ??????? ???? ?? ??? ??? ?? ?? ?? ???????? ?? ????? ?? ??? ??? ?? ?????? ???????????? ?? ?????? ?? ??? ?? ????? ?? ????? ???? ?? ??? ???????????? ?? ????? ???? ?? ??? Windows XP ??????????? ?? ??? ?????? ???

?? ???? ????? ???? ?? ?? ?????????? ???? ?? ????? ????? ??? ??? ????? ?? ???????? ???? ?? ??? ???? ????:
  • ?? Win32 ????????? ??????
  • ????? ????? ??? ??? ?????????? ?? ??? ?????????????? ??..
  • ???? ?? ????? ????????? ??????????? ????? ?? ??? ????? ?? ??????? ???
  • ??? ????? ?????? ?? ????? ?? ???? ?????
  • ?????????? ?? ????? ??? ??? ?????
  • ?????????? ?? ????? ??? ?? ???? ?????
????? ????? ??? ?? ???? ????? ?? ?? ???? ?? ????????? ???? ?????? ???? ???? ?? ?? ?? ??????? ??????? ??? ???????? ?? ?? ?? ????????? ???? ?? ??? ???? ????:
  • ????????? ???? classify ???
  • ????????? ???? ?? ??? ????? ?? ?????? ?????
  • ????????? judiciously ?? ????? ?????

??????????

????? ???? outlines ???????? ?????????, ??????????, ??????? ??????, ????, ???????, ?? ???? ???? ???:
  • Windows XP Home ??????? ?? Windows XP Professional
  • ????? Studio 2008, ????? Sudio 2005 ?? Visual Studio .NET.
  • Win32 ????????? ????? ?? ????? ???????

?? Win32 ????????? ?????

Visual Studio ??????? ????, ?? ??? ??? Win32 ????????? SavingData ??? ??????
  • Visual Studio .NET, ??? ????? ????????? C++ ??????????? ???????????????? ???????? ????-????? ????, ?? ???? ???Win32 ??????????? ???????????????. ????????? ????? ???????? ????????? ???? ?? ?? ??????? ????????? ???????? ??????? ?????
  • Visual Studio 2005 ?? 2008, ??? ????? ????????? C++?? ???????????????? ???????? ????-????? ????, ?? ???? ???Win32 ??????????? ???????????????. ??????? ????????? ???????? ??????? ?????

????? ???? ?? ' ?????? ?? ??? ??? ?????? ???? ?? ?????

  1. ????? ????,?????? ?????????? ????, ?? ???? ???IDC_SAVINGDATA.
  2. ????? ????? ??? ??? ?????????? ?? ??? ?????? ???????????? ??.. ?????IDM_FILE_SAVEAS?? ??? ??? ???? ???? ?? ID.
  3. ????????? ?? ?????? ?????WndProcSavingData.cppm ??? ????? ????????? ?? ??? ??? ???????????????????? ??? ?? ????WM_COMMAND????????? ???? ?? ??? ???????? ??? ??? ?????????? ?? ??????? ???OnFileSaveAs??????, ?? ???? ?????? ??? ??? ????? ?? ?????? ??? ???????? ???? ???

    ???? ??? ?? ??? ??? ????? ???? ?????:
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        case IDM_FILE_SAVEAS:
            OnFileSaveAs(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    

??? ????? ?? ??? ???? ???? ?????? ????? ????? ??? ??????? ?? ????? ????

?? ??? ?????????? ??? ????????? ?????????????? ??????(?????? ?????) ?????????? ?? ???? ????????? ??????? (?? ???? ?????????, ???? ??? ??? ???? ?? ??? ???? ????? ?? ???? ????? ?? ??? ????? ??????? ?? ?? descendant) ?? ??? ????? ????? ??? ???? ???, ????? ????? ?? ??? ??????? ???? ?????

???:: ?? ?????? ????? ??? ???? ??? ??? ?? ???? ????????? ??? ??????? ?? ?????? ?? ?? ???? ??? ??? ? ?? ???? ????? ?????? ?????? ?? ???, ???? ?????????? ?? ???? ??????? ????? ???? ????????? ??????? relocate ?? ???? ???
  1. SavingData.cpp ?? ????? ?? ????? ????? ????? ??????:
    #include <commdlg.h>   // for GetSaveFileName
    #include <shlobj.h>    // for SHGetFolderPath
    					
  2. ?? ??? ????? ?????????? ??????OnFileSaveAs?????? ?? ??? ???? ???.:
    void OnFileSaveAs( HWND hWnd );
    					
  3. ??? ?????OnFileSaveAs?????? ?? ??? ???? ???.. ?? ?????? ?? ?????SHGetFolderPath??? ??? ??????CSIDL_MYPICTURESCSIDL?????????? ?? ???????? ???? ?? ??? ??? ??????? ????? ??????? ???? ?? ??? ???? ?????? ?? ??????? ?? ???? ?? ??? ????? ?? ???GetSaveFileName???? ????????? ???? ?? ??? ??????????? ??????????? ????? ?? ??????? ?? ??? ?? ..

    ???? ??? ?? ??? ??? ????? ???? ?????:
    void OnFileSaveAs(HWND hWnd)
    {
       OPENFILENAME openFile;
       TCHAR szPath[MAX_PATH];
       TCHAR szFile[MAX_PATH];
    
        // Initialize OPENFILENAME structure.
        ZeroMemory( &openFile, sizeof(OPENFILENAME) );
        openFile.lStructSize = sizeof(OPENFILENAME);
    
        szFile[0] = '\0';
        openFile.hwndOwner = hWnd;
        openFile.lpstrFile = szFile;
        openFile.nMaxFile = sizeof(szFile)/sizeof(*szFile);
    
        // Default to My Pictures. First, get its path.
        if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_MYPICTURES, 
                                              NULL, 0, szPath ) ) )
        {
           // Set lpstrInitialDir to the path that SHGetFolderPath obtains. 
           // This causes GetSaveFileName to point to the My Pictures folder.
              openFile.lpstrInitialDir = szPath;
        }
        // Display the standard File Save dialog box, defaulting to My Pictures.
        if ( GetSaveFileName( &openFile ) == TRUE )
        {
            // User clicks the Save button.
            // Save the file
        }
        else
        {
           // User cancels the File Save dialog box.
        }
    }
    

??????? ???? ?????? ????? ?? ???? ????

  1. ????????? ????? ?? ??? F5 ????? ??????
  2. ????? ????, ?? ????????? ??????? ??? ??? ???????????????? ??..
  3. ?????? ???? ?? ????????? ??????????? ???? ?? ??? ???? ????? ?????? ??????? ?? ??? ??? ?????CSIDL_MYPICTURES????????? ???? ???
  4. ????? ????,???? ????????? ????? ??? ????, ?? ????????? ??? ?????

???????? ????? ??? ??? ????

?? ?????? ????? ?? ???????? ??????(?????? ?????) ????? ????? ???, ?? ???????? ?? ?? ?????????? ?? ??? ??????? ????? ????? ???? ?? ????? ??????

??? ?? ??? ?? ????????? ??????? ????? ?????? ?? ????OPENFILENAME?????? ?? ???,GetSaveFileName(??GetOpenFileName) ???? ????????? ????????? ????????,???? ?????????? ????? ???, ?? ???? ????????? ??????? ?? ????? ???? ??? ???? ??? ??, ??? ?????????? ?? ????? ?? ????? ?????? ??? ?? ?? ????? ?? ?? ???-??????? ?????? ???? ??, ?? ?????? ???? ?? ??????? ?????? ???? ?? ????? ???? ?? ????

To support the recommended best practice of targeting a specific folder location (such as My Pictures) the first time a user saves or loads a file, and to subsequently default to the user's previously selected location, you should use a Boolean variable to track whether this is the first time the user has performed the Save or Open operation.
  1. ????? ???static BOOLvariable namedbFirstSave?????OnFileSaveAsfunction, and initialize it toTrue.
  2. Modify the code withinOnFileSaveAsto callSHGetFolderPath?? ??? ????lpstrInitialDir?? ?????OPENFILENAMEstructure, only ifbFirstSave??True.
  3. If the user clicks???????????????? ??????dialog box, setbFirstSave???? ?? ??????.

    Your code should appear as follows:
    void OnFileSaveAs(HWND hWnd)
    {
        OPENFILENAME openFile;
        TCHAR szPath[MAX_PATH];
        TCHAR szFile[MAX_PATH];
        static BOOL bFirstSave = TRUE;
    
        // Initialize OPENFILENAME structure.
        ZeroMemory( &openFile, sizeof(OPENFILENAME) );
        openFile.lStructSize = sizeof(OPENFILENAME);
    
        szFile[0] = '\0';
        openFile.hwndOwner = hWnd;
        openFile.lpstrFile = szFile;
        openFile.nMaxFile = sizeof(szFile)/sizeof(*szFile);
    
        // The first time the user saves a document, default to My Pictures.
        if ( TRUE == bFirstSave )
        {
            if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_MYPICTURES, 
                NULL, 0, szPath ) ) )
            {
                // Set lpstrInitialDir to the path that SHGetFolderPath obtains.
                // This causes GetSaveFileName to point to the My Pictures folder.
                openFile.lpstrInitialDir = szPath;
            }
        }
        // Display standard File Save dialog box, defaulting to My Pictures
        // or the user's previously selected location.
        if ( GetSaveFileName( &openFile ) == TRUE )
        {
            // User clicks Save.
            // Save the file.
            bFirstSave = FALSE;
        }
        else
        {
            // User cancels the File Save dialog box.
        }
    }
    

Verify the User's Previous Selection

  1. Build the project, and run the application.
  2. ?????????? ??,?? ??? ??? ??????.
  3. Browse from the My Pictures folder to the My Documents folder, select a file, and click??????.
  4. ?????????? ??,?? ??? ??? ?????????:?
  5. Verify that the dialog box defaults to your previous selection (in this case, My Documents).
  6. ????? ????,???? ????to dismiss the dialog box, and close the application.
  7. Run the application, and click?? ??? ??? ???????????????? ??..
  8. Verify that the dialog box defaults back to the My Pictures folder.
  9. Close the dialog box, and quit the application.

Classify Application Data

You should not store application-specific data (such as temporary files, user preferences, application configuration files, and so on) in the My Documents folder. Instead, use either an appropriate location in the Windows Registry (for data that does not exceed 64 kilobytes) or an application-specific file that is located in a valid Application Data folder.

????????? ???? corrupting ?? ??-????? ?? ???? ?? ???????? ?? ???????? ???? ?? ???? ?? ?? ???????? ?? ????? ???? ?? ??? ?? ????? ?? ?????? ???? ?? ??? ??? ????? ?? ???????? ???? ?? ??? ?????????? ???

???? ????????? ???? ?? ??? ???? ??????? ????? ????????, ???? ???? classify ???? ?? ??? ????? ????????? ?? ????? ????:
  • ???????? ?????????? (??????) ?? ???: ?????? ?? ????????? ???? ?? ???? ????? ?????????? ?? ??? ??????? ?? ?? ???? ????? ?????? ???? ?? ??? ?????????? ?? ??? ??? ?? ???? ?? ?? (?????? ?? ???, ??? ????? ???????) ???? ????? ??? ???????? ?? ??? ?? ????? ???? ??? ????? ??? ?? ?? ?????? ???? ???? ???? ?? ??? ????????? ?? ???? ????? ?? ??????? ??? ????? ?? ??? ??????? ???? ???? ??? ????
  • ???????? ?????????? (???-??????) ?? ???: ?????? ?? ????? ???? ?? ?? ????????? ???? ?? ???? ????? ?????????? ?? ??? ??????? ??, ????? ???? ??? ??? ???????? (?????? ?? ???, ???? ?????????? ????????? ?????? ???????????) ?? ???? ???? ???
  • ???????? ???????? (???-??????????-??????? ?? ???-??????) ?? ???: ?????? ?? ?? ???? ???? ?? (?????? ?? ???, ??? ????????? ???????, ?? ??? ?????, ?? ???? ??????? ?????) ??? ????? ???????? ?? ??? ?? ??? ???????????? ?? ??? ????????? ???? ?? ????? ???? ???

????????? ???? ?????? ????? ???????

?? ?? ????? ????SHGetFolderPath????????? ???? ?? ??? ??????? ?? ??????? ???? ?? ??? ????? ????? ?? ?????? ??? ????????? ???? ???????? ???? ????? Instead, use thePathAppendfunction to append a subfolder to the path thatSHGetFolderPath???? ??? Make sure that you use the following convention:
Company Name\Product Name\Product Version
For example, the resultant full path may appear as follows:
\Documents and Settings\All Users\Application Data\My Company\My Product\1.0
To locate the correct Application Data folder, pass the appropriateCSIDLvalue, based on the category of your application data.
  • For each user (roaming) data, use theCSIDL_APPDATAValue:. This defaults to the following path:
    \Documents and Settings\?????????? ?? ???>\Application Data
  • For each user (non-roaming) data, use theCSIDL_LOCAL_APPDATAValue:. This defaults to the following path:
    \Documents and Settings\?????????? ?? ???>\Local Settings\Application Data
  • For each computer (non-user specific and non-roaming) data, use theCSIDL_COMMON_APPDATAValue:. This defaults to the following path:
    \Documents and Settings\All Users\Application Data
The following code fragment demonstrates how to open a temporary log file, which is located beneathCSIDL_COMMON_APPDATA:
include <shlwapi.h>
#pragma comment(lib,"shlwapi.lib")
void CreateTemporaryFile()
{
   TCHAR szPath[MAX_PATH];
   // Get path for each computer, non-user specific and non-roaming data.
   if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_COMMON_APPDATA, 
                                    NULL, 0, szPath ) ) )
   {
      TCHAR szTempFileName[MAX_PATH];
      // Append product-specific path - this path needs to already exist
      // for GetTempFileName to succeed.
      PathAppend( szPath, _T("\\My Company\\My Product\\1.0\\") );
      // Generate a temporary file name within this folder.
      if (GetTempFileName( szPath, 
                           _T("PRE"),
                           0,
                           szTempFileName ) != 0 )
      {
         HANDLE hFile = NULL;
         // Open the file.
         if (( hFile = CreateFile( szTempFileName, 
                                   GENERIC_WRITE, 
                                   0, 
                                   NULL, 
                                   CREATE_ALWAYS, 
                                   FILE_ATTRIBUTE_NORMAL, 
                                   NULL )) != INVALID_HANDLE_VALUE )
         {
            // Write temporary data (code omitted).
            CloseHandle( hFile );
         }
      }
      else
          DWORD err = GetLastError();
   }
}

Use the Registry Judiciously

???????????? ???, ????, ?? ????? ?? ????????? ?? ??????? ???? ?? ??? ????? ????? ??? ???? ???????, ??? ?? ????????? ?? ??? ??? ?? ??????? ???? ??? ?? ????? ???????? ??????? ?? ???? ???.. ?????, ????????? ???? ?? ?? ?? ????? ?? ??????????? ???? ???? ???.. ?????? ??????? ?? ???, ????????? ?? ??????? ???? ?? ???? ???? ??? ?? ???.. ???, ??? ??? ?????? ??????? ???? ?? ?? ?? ????????? ?? ???????????? ?? ???? ???.. ????????? ?? ??? ?? ???? ?? ???????????? ???? ?? ????? ?? ???? ??? ???? ??????? ?? ???, Microsoft ?????? ??? ??? ???? ????? ?? ??? ????? ???? ?????? ????? ????::
322756  (http://support.microsoft.com/kb/322756/ ) ??? ?? ???? ?? Windows ??? ????????? ?? ???????????? ???? ????

You can also use the registry to store small amounts of application data. For data that exceeds 64 kilobytes (KB), you must use an Application Data folder. Observe the following guidelines when you use the registry to store application data:
  • For small amounts of user data, use theHKEY_CURRENT_USER(HKCU) registry key.
  • For small amounts of computer data, use theHKEY_LOCAL_MACHINE(HKLM) registry key. Your application should not write toHKLMat run time because, by default, non-administrator users only have read-only access to theHKLM?????
  • At installation time, your application must not store more than a total of 128 KB acrossHKCU, ??HKLM.
  • Component Object Model (COM) components are registered beneath theHKEY_CLASSES_ROOT(HKCR) registry key. The 128 KB maximum does not includeHKCR.
  • When you write toHKLM??,HKCU, you must create keys for the company name, product name, and product version number, as follows:
    HKLM\Software\Company Name\Product Name\Product Version
    HKCU\Software\Company Name\Product Name\Product Version
  • Use the registry functions (such asRegCreateKeyEx, ??RegSetValueEx) to read and write registry entries.

?????? ??????

  • To help ensure that applications run on earlier versions of Windows in addition to Windows XP, always link to theSHGetFolderPathimplementation in Shfolder.dll. Although Windows XP includesSHGetFolderPathin Shell32.dll, earlier versions of Windows may not support the function within this dynamic-link library (DLL).
  • Shfolder.dll is a redistributable component and may be distributed with your applications.
  • Do not store fully-qualified paths to the My Documents folder (or other system folders) within an application-specific place such as a file list of most recently used files because a user or Administrator may relocate these folders between successive uses of your application.

??????

For other top-hit Visual C++ .NET Microsoft Knowledge Base articles, visit the Visual C++ .NET Support Center at the following Microsoft Web site:
Visual C++ .NET (2002) Support Center
http://support.microsoft.com/default.aspx?xmlid=fh%3BEN-US%3Bvcnet (http://support.microsoft.com/default.aspx?xmlid=fh%3BEN-US%3Bvcnet)
For more general information about Visual C++ .NET, visit the following Microsoft Usenet newsgroup:
Microsoft.public.dotnet.languages.VC (http://msdn.microsoft.com/newsgroups/default.aspx?query=Microsoft.public.dotnet.languages.vc&dg=&cat=en-us-msdn&lang=en&cr=US&pt=&catlist=774F24A2-F71F-425F-AC2B-DC48AB0DA5C9&dglist=&ptlist=&exp=&sloc=en-us)
For more information about the complete set of folders thatSHGetFolderPathcan identify, see the following Microsoft Platform Software Development Kit (SDK) documentation:
CSIDL
http://msdn.microsoft.com/en-us/library/bb762494.aspx (http://msdn.microsoft.com/en-us/library/bb762494.aspx)
For more information about shell programming in general, see the following Microsoft Developer Network (MSDN) Web site:
Shell Programmers Guide
http://msdn2.microsoft.com/en-us/library/bb776778.aspx (http://msdn2.microsoft.com/en-us/library/bb776778.aspx)

???? ???? ???? ??:
  • Microsoft Visual C++ 2008 Express Edition
  • Microsoft Visual C++ 2005 Express Edition
  • Microsoft Visual C++ .NET 2003 Standard Edition
  • Microsoft Visual C++ .NET 2002 Standard Edition
??????: 
kbhowtomaster kbnewsgrouplink kbmt KB310294 KbMthi
???? ?????? ???????????? ?????? ????????
??????????: ?? ???? ?? ???? ??????? ?? ????? ?? Microsoft ????-?????? ?????????? ?????? ?????? ???? ??? ??. Microsoft ???? ??? ????-???????? ?? ????-???????? ????? ?????? ?? ???? ???????? ???? ?? ???? ????? ????? ??? ?? ??? ?????? ?? ???? ???? ???? ??? ????? ??. ???????, ????-???????? ???? ????? ???? ???? ???? ???. ?????, ????????, ?????-???? ?? ??????? ?? ???????? ?? ???? ???, ???? ?? ??? ?????? ???? ???? ??? ????? ??? ?? ???? ??. Microsoft ??????? ??? ???? ?? ?????? ?? ??????????, ????????? ?? ??? ?????? ?? ???? ????? ?? ???? ???????? ?? ??? ???? ????? ?? ??? ????????? ???? ??. Microsoft ????-?????? ?????????? ?? ????? ?????? ?? ?? ??? ??.
?????????? ?? ??????? ????????? ??????? ??:310294  (http://support.microsoft.com/kb/310294/en-us/ )