HOW TO:使用 Visual C++.NET 撰寫將使用者與應用程式資料儲存於正確位置的 Windows XP 應用程式

文章翻譯 文章翻譯
文章編號: 310294 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

結論

應用程式運用兩種類型的文件:由使用者建立的文件,及由應用程式所建立的文件。您的應用程式可以使用 SHGetFolderPath shell 函數,擷取正確的資料夾位置,以存放特定使用者與應用程式的資料。這對於支援多位使用者使用同一台電腦,並讓使用者可以迅速切換的 Windows XP 應用程式而言是很重要的。

本文將告訴您,如何以下列的步驟將使用者的資料存放於正確的位置:
  • 建立 Win32 應用程式。
  • 新增 [另存新檔] 選項到 [檔案] 功能表。
  • 使用標準的 [檔案儲存] 對話方塊預先定義的正確位置。
  • 確認正確的檔案儲存位置。
  • 記憶使用者先前的選擇。
  • 確認使用者先前的選擇。
在下列的步驟中,本文也會告訴您必須把應用程式資料存放在哪裡,以及如何確定它是存放在適當的位置:
  • 分類應用程式資料。
  • 存放應用程式資料到正確的位置。
  • 謹慎地使用登錄。

需求

下面清單提列了建議使用的硬體、軟體、網路基礎架構以及所需安裝的 Service Pack:
  • Windows XP Home Edition (家用版) 和 Windows XP Professional (商用版)
  • Visual Studio .NET 或 Visual Studio version 6.0
  • Win32 應用程式開發的優越知識

建立 Win32 應用程式

啟動 Visual Studio,並且建立一個名為 SavingData 的新 Win32 應用程式。
  • 在 Visual C++ 6.0 中,從可用的專案類型清單中按一下 [Win32 應用程式] ,然後在應用程式安裝精靈中選取 [一個典型的 Hello World 應用程式] 選項。
  • 在 Visual Studio .NET,按一下 [專案類型] 下面的 [Visual C# 專案],再按一下 [範本] 下面的 [Win32 專案]。接受應用程式安裝精靈所顯示的預設應用程式設定。

新增另存新檔選項到檔案功能表

  1. 按一下 [資源檢視],然後按兩下 [IDC_SAVINGDATA]
  2. 新增 [另存新檔] 功能表選項到 [檔案] 功能表中。使用 IDM_FILE_SAVEAS 做為功能表項目的 ID。
  3. 在 SavingData.cppm 內尋找應用程式的 WndProc window 程序,並在 WM_COMMAND 區段內新增新的 case 陳述式,以處理 [另存新檔] 功能表選項。呼叫 OnFileSaveAs 函數, 您可以在下個區段中加以建立。這個函數沒有任何的參數。

    您的程式碼應該如下所示:
    case WM_COMMAND:
       wmId    = LOWORD(wParam); 
       wmEvent = HIWORD(wParam); 
       // Parse the menu selections.
       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;
    					

使用標準的檔案儲存對話方塊預先定義正確的位置

當使用者第一次顯示應用程式的 [檔案儲存] (或 [檔案開啟]) 對話方塊時,對話方塊必須預設為使用者的 [我的文件] 資料夾 (或 [我的文件] 的子資料夾,例如存放影像資料的 [My Pictures] 與存放音訊檔的 [My Music])。

注意:千萬不要將應用程式內的路徑寫死,因為您永遠無法保證它的實體位置。例如,系統管理員可能會將 [我的文件] 資料夾重新配置到網路上的位置。
  1. 在 SavingData.cpp 的上方,新增下列的 include 陳述式:
    #include <commdlg.h>   // for GetSaveFileName
    #include <shlobj.h>    // for SHGetFolderPath
    					
  2. 將下列的原型新增給 OnFileSaveAs 函數:
    void OnFileSaveAs();
    					
  3. 建立新的 OnFileSaveAs 函數。在這個函數內,將 SHGetFolderPath 函數與 CSIDL_MYPICTURESCSIDL 識別項描配使用,以擷取存放圖片資料的正確資料夾位置。將這個資料夾位置傳遞到 GetSaveFileName 函數,以顯示標準的 [檔案儲存] 對話方塊。

    您的程式碼應該如下所示:
    void OnFileSaveAs()
    {
       OPENFILENAME openFile;
       TCHAR szPath[MAX_PATH];
    
    // Initialize OPENFILENAME structure.
    ZeroMemory( &openFile, sizeof(OPENFILENAME) );
    openFile.lStructSize = sizeof(OPENFILENAME);
    // 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. 確認 [檔案儲存] 對話方塊預設至 [My Pictures] 資料夾,如 CSIDL_MYPICTURES 指定的。
  4. 按一下 [取消] 以關閉對話方塊,並結束應用程式。

記憶使用者先前的選擇

為了之後使用 [檔案儲存] (或 [檔案開啟]) 對話方塊,建議您將該對話方塊預設到使用者先前選取的位置。

如果您沒有在 OPENFILENAME 結構內提供初始的資料夾位置,則 GetSaveFileName (及 GetOpenFileName) 會顯示標準的 [檔案儲存][檔案開啟] 對話方塊,它指向 [我的文件] 資料夾。此外,如果使用者之前已經用過這些對話方塊的其中一個,並且選擇了一個非預設的資料夾,則這些函數會自動預設為先前使用的資料夾。

為了支援所建議之最佳慣例目標資料夾位置 (例如 [My Pictures]),使用者第一次儲存或是載入檔案後,使用者先前選取的位置會隨之設定為預設值,您可以使用布林變數,追蹤這是否為使用者初次執行儲存或是開啟作業。
  1. OnFileSaveAs 函數中建立一個命名為 bFirstSavestatic BOOL 變數,並將它初始為 TRUE
  2. OnFileSaveAs 內修改程式碼,以呼叫 SHGetFolderPath 並將 lpstrInitialDir 設定為 OPENFILENAME 結構的成員 (僅限當 bFirstSaveTRUE 時)。
  3. 如果使用者按一下 [檔案儲存] 對話方塊中的 [儲存] ,則將 bFirstSave 設定為 FALSE

    您的程式碼應該如下列所示:
    void OnFileSaveAs()
    {
       OPENFILENAME openFile;
       TCHAR szPath[MAX_PATH];
       static BOOL bFirstSave = TRUE;
    
    // Initialize OPENFILENAME structure.
    ZeroMemory( &openFile, sizeof(OPENFILENAME) );
    openFile.lStructSize = sizeof(OPENFILENAME);
    // 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.
    }
    }
    					

確認使用者先前的選擇

  1. 建置並執行此應用程式。
  2. [檔案] 功能表上按一下 [另存新檔]
  3. 從 [My Pictures] 資料夾瀏覽到 [我的文件] 資料夾,選取一個檔案,並按一下 [儲存]
  4. [檔案] 功能表上再按一下 [另存新檔]
  5. 確認那個對話方塊預設為您先前的選取 (在這個案例中是 [我的文件])。
  6. 按一下 [取消] 以退出對話方塊,並且關閉應用程式。
  7. 執行應用程式,並按一下 [檔案] 功能表中的 [另存新檔]
  8. 確認那個對話方塊預設為回到 [My Pictures] 資料夾。
  9. 關閉對話方塊,並結束應用程式。

分類應用程式資料

您不應該將應用程式特定的資料 (例如暫時檔、使用者喜好設定、應用程式組態檔等等) 存放在 [我的文件] 資料夾。相反地,應該使用 Windows 登錄中的適當位置 (適用於不超過 64 KB 的資料) 或是位在正確 [Application Data] 資料夾內的應用程式特定檔。

在正確的位置存放應用程式資料是很重要的,如此才能讓多個人使用同一部電腦,而不會損毀或是覆寫彼此的資料和設定。

如果要判斷應用程式資料的最適當位置,請使用以下的類別分類您的資料:
  • 每個使用者 (漫遊):這個類別描述了特定使用者的特殊應用程式資料,並且使用者可以在相同網域內的電腦中移動時使用 (例如,使用者自訂的字典)。請注意,這個設定無法套用於在網域環境中執行的應用程式。
  • 每個使用者 (非漫遊):這個類別描述了特定使用者的特殊應用程式資料,但是僅能運用於單一的電腦上 (例如,使用者特定的監視器解析度)。
  • 每台電腦 (非使用者特定與非漫遊):這個類別描述了套用在所有使用者及特定電腦的應用程式資料 (例如,應用程式目錄、記錄檔,或暫時檔)。

在正確的位置存放應用程式資料

您可以使用 SHGetFolderPath 函數,擷取正確的 [Application Data] 資料夾。請勿直接存放此資料夾中的應用程式資料。相反地,使用 PathAppend 函數,將子資料夾附加到 SHGetFolderPath 傳回的路徑。確認您使用了下列的慣例:
公司名稱\產品名稱\產品版本
例如,所產生的完整路徑可能類似於以下所列:
\Documents and Settings\All Users\Application Data\My Company\My Product\1.0
如果要尋找正確的 [Application Data] 資料夾,請依據應用程式的類別傳遞適當的 CSIDL 值。
  • 對每個使用者 (漫遊) 資料,使用 CSIDL_APPDATA 的值。這個預設為以下的路徑:
    \Documents and Settings\<User Name>\Application Data
  • 對每個使用者 (非漫遊) 資料,使用 CSIDL_LOCAL_APPDATA 的值。這個預設為以下的路徑:
    \Documents and Settings\<User Name>\Local Settings\Application Data
  • 對每部電腦 (非使用者特定與非漫遊) 資料,使用 CSIDL_COMMON_APPDATA 的值。這個預設為以下的路徑:
    \Documents and Settings\All Users\Application Data
下列的程式碼片段示範了如何開啟暫時的記錄檔,其位於 CSIDL_COMMON_APPDATA之下:
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.
      PathAppend( szPath, "\\My Company\\My Product\\1.0\\" );
      // Generate a temporary file name within this folder.
      if (GetTempFileName( szPath, 
                           "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 );
         }
      }
   }
}
				

謹慎地使用登錄

警告:如果使用登錄編輯器的方式不正確,可能會導致必須重新安裝作業系統的嚴重問題。Microsoft 不保證您可以解決錯誤使用登錄編輯器所造成的問題。請自行承擔使用登錄編輯器的一切風險。

您也可以使用登錄,存放小量的應用程式資料。對於超出 64 KB 的資料,您必須使用 [Application Data] 資料夾。當您使用登錄,存放應用程式資料時,請遵守下列的準則:
  • 對於小量的使用者資料,使用 HKEY_CURRENT_USER (HKCU登錄機碼。
  • 對於小量的電腦資料,使用 HKEY_LOCAL_MACHINE (HKLM) 登錄機碼。在執行期間,您的應用程式不可以寫入 HKLM ,因為依預設,非系統管理員的使用者對於 HKLM 樹狀目錄僅擁有唯讀的存取權。
  • 在安裝時間,跨越 HKCUHKLM,應用程式的存放總數絕不能超過 128 KB。
  • 元件物件模型 (COM) 元件會登錄在 HKEY_CLASSES_ROOT (HKCR) 登錄機碼之下。最大 128 KB, 尚不包括 HKCR
  • 當您寫入 HKLMHKCU時,您必須建立公司名稱、產品名稱,及產品版本號碼的機碼,如下所示:
    HKLM\Software\Company Name\Product Name\Product Version
    HKCU\Software\Company Name\Product Name\Product Version
  • 使用登錄函數 (例如 RegCreateKeyExRegSetValueEx),讀取和寫入登錄項目。

疑難排解

  • 為了協助確認應用程式可以在 Windows XP 之外較舊的 Windows 版本上執行,請永遠連結到在 Shfolder.dll 的 SHGetFolderPath 實作。雖然 Windows XP 在 Shell32.dll 中包括了 SHGetFolderPath ,較舊的 Windows 版本在此動態連結程式庫 (DLL) 中並未支援該函數。
  • Shfolder.dll 是一個可轉散發元件,並且可以與您的應用程式一起散佈。
  • 在應用程式特定的位置之內,請不要將完整格式的路徑存放到 [我的文件] 資料夾 (或是其他的系統資料夾),例如最近使用過的檔案清單 ,因為使用者或系統管理員可能會在隨後您所使用的應用程式之間,重新配置這些資料夾。

?考

如需其他常被點選之 Visual C++ .NET Microsoft Knowledge Base 文件,請造訪下列 Microsoft 網站的 Visual C++ .NET 支援中心:
Visual C++ .NET (2002) 支援中心
http://support.microsoft.com/default.aspx?scid=fh;EN-US;CNTACTMS
如需更多有關 Visual C++ .NET 的一般性資訊,請造訪下列 Microsoft Usenet 新聞群組:
Microsoft.public.dotnet.languages.vc
如需有關 SHGetFolderPath 能夠識別之完整資料夾集合的詳細資訊,請參閱下列的 Microsoft Platform Software Development Kit (SDK) 說明文件:
CSIDL
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iisref/html/psdk/asp/vbob1dtg.asp
如需有關 Shell 程式設計的詳細資訊,請查詢下列 Microsoft Developer Network (MSDN) 網站:
Shell Programmers Guide
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iisref/html/psdk/asp/vbob1dtg.asp

屬性

文章編號: 310294 - 上次校閱: 2003年5月26日 - 版次: 1.1
這篇文章中的資訊適用於:
  • Microsoft Visual C++ .NET 2002 Standard Edition?應用於:
    • Microsoft Windows XP Professional
關鍵字:?
kbhowto kbhowtomaster kbnewsgrouplink KB310294
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

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