天天看點

MFC中GetPrivateProfileString相關函數

項目中用到了這個函數,是以了解了一下,參考了一些部落格:

http://blog.sina.com.cn/s/blog_a599b5960101tsbk.html

http://blog.csdn.net/artmcu/article/details/8077815(連着三篇)

http://www.cnblogs.com/rosesmall/archive/2012/09/12/2681897.html

自己又動手實作了一下,又發現#include<afx.h>隻能在MFC工程中用到,修改屬性--->正常---->MFC的使用----->選擇(在共享 DLL 中使用 MFC),還有C/C++中-->代碼生成--->運作庫--->最後一個(/MDd)。

::WritePrivateProfileString( _T("Options"), _T("Name"), m_strName, pApp->m_szIni );

INI檔案程式設計,WINAPI函數WritePrivateProfileString,GetPrivateProfileString 收藏

    在我們寫的程式當中,總有一些配置資訊需要儲存下來,以便完成程式的功能,最簡單的辦法就是将這些資訊寫入INI檔案中,程式初始化時再讀入.具體應用如下:

  一.将資訊寫入.INI檔案中.

  1.所用的WINAPI函數原型為:

BOOL WritePrivateProfileString(

LPCTSTR lpAppName,

LPCTSTR lpKeyName,

LPCTSTR lpString,

LPCTSTR lpFileName

);

  其中各參數的意義:

   LPCTSTR lpAppName 是INI檔案中的一個字段名.

   LPCTSTR lpKeyName 是lpAppName下的一個鍵名,通俗講就是變量名.

   LPCTSTR lpString 是鍵值,也就是變量的值,不過必須為LPCTSTR型或CString型的.

LPCTSTR lpFileName 是完整的INI檔案名.

2.具體使用方法:設現有一名學生,需把他的姓名和年齡寫入 c:\stud\student.ini 檔案中.

CString strName,strTemp;

int nAge;

strName="張三";

nAge=12;

::WritePrivateProfileString("StudentInfo","Name",strName,"c:\\stud\\student.ini");

此時c:\stud\student.ini檔案中的内容如下:

[StudentInfo]

   Name=張三

  3.要将學生的年齡儲存下來,隻需将整型的值變為字元型即可:

strTemp.Format("%d",nAge);

::WritePrivateProfileString("StudentInfo","Age",strTemp,"c:\\stud\\student.ini");

  二.将資訊從INI檔案中讀入程式中的變量.

DWORD GetPrivateProfileString(

LPCTSTR lpDefault,

LPTSTR lpReturnedString,

DWORD nSize,

   前二個參數與 WritePrivateProfileString中的意義一樣.

   lpDefault : 如果INI檔案中沒有前兩個參數指定的字段名或鍵名,則将此值賦給變量.

   lpReturnedString : 接收INI檔案中的值的CString對象,即目的緩存器.

   nSize : 目的緩存器的大小.

   lpFileName : 是完整的INI檔案名.

  2.具體使用方法:現要将上一步中寫入的學生的資訊讀入程式中.

CString strStudName;

int nStudAge;

GetPrivateProfileString("StudentInfo","Name","預設姓名",strStudName.GetBuffer(MAX_PATH),MAX_PATH,"c:\\stud\\student.ini");

//MAX_PATH:是微軟最大路徑占的位元組所設的宏

  執行後 strStudName 的值為:"張三",若前兩個參數有誤,其值為:"預設姓名".

     在GetPrivateProfileString最後一個參數是配置檔案路徑的參數,此路徑隻能是絕對路徑,不能是相對路徑,但現在我需要是我的exe檔案能和我的配置檔案在一起。是以我使用了GetCurrentDirectory函數。

原代碼如下:

CString server_ip;

CString des="";

::GetCurrentDirectory(MAX_PATHLENGTH,des.GetBuffer(MAX_PATHLENGTH));

des.ReleaseBuffer();

des+="\\config.ini";

GetPrivateProfileString("PhoneDemo","Server_IP","",server_ip.GetBufferSetLength(15),15,des);

server_ip.ReleaseBuffer();

注意:在這裡使用CString變量時,在使用完GetBuffer後,緊接着一定要使用ReleaseBuffer()函數,才可以進行其他的諸如字元串+操作

  3.讀入整型值要用另一個WINAPI函數:

UINT GetPrivateProfileInt(

INT nDefault,

  這裡的參數意義與上相同.使用方法如下:

nStudAge=GetPrivateProfileInt("StudentInfo","Age",10,"c:\\stud\\student.ini");

更多說明:
擷取路徑
GetCurrentDirectory隻是傳回目前程序的目前目錄,而并不是程序的鏡像檔案(.exe)所在的目錄
GetCurrentDirectory()适用于XP等系統,在WinCE上不能使用
GetModuleFileName()适用于WinCE2.0以後
使用方法:
//下面的一段代碼主要是獲得目前程式的運作目錄(.exe)所在的目錄
{
    CString path;
    GetModuleFileName(NULL,path.GetBufferSetLength(MAX_PATH+1),MAX_PATH);
    path.ReleaseBuffer();
    int pos = path.ReverseFind('\\');
    path = path.Left(pos);
}
GetModuleFileName函數
WINAPI DWORD GetModuleFileName(
  HMODULE hModule,
  LPWSTR lpFilename,
  DWORD nSize
);
      GetBuffer和ReleaseBuffer是一套需要配合使用的函數, 與GetBufferSetLength相比, 優點是如果配置設定的空間大于實際儲存的字元串(0結尾),
ReleaseBuffer會把多餘申請的空間釋放, 歸還給系統; 但使用時需要注意以下問題: 如果要儲存的字元串為abc(0結尾),則GetBuffer參數應至少
為3; 如果要儲存的内容不是以0結尾, 比如是讀取檔案資料, 則GetBuffer參數如果大于檔案長度時,ReleaseBuffer參數一定要為檔案長度(如果
GetBuffer參數為檔案長度的話不存在問題,ReleaseBuffer參數可以為預設-1)!
 GetBufferSetLength相對比較容易了解, 它申請一個指定長度的空間, 即使裡面最終儲存的字元串長度小于申請的空間長度, 也不會将多餘空間釋放.
__________________________________________________________________________________________________________________DWORD GetCurrentDirectory(
  DWORD nBufferLength,
  LPTSTR lpBuffer
);The GetCurrentDirectory function retrieves the current directory for the current process.GetCurrentDirectory傳回目前程序的目前目錄,并不一定傳回你的應用程式的目錄。如果你在應用程式中調用了打開檔案對話框,你選擇了一個檔案,那麼,這個檔案所在的目錄就成了目前程序的目前目錄了。Parameters
nBufferLength: 接收儲存路徑的字元串緩存長度, 緩存必須有一個儲存結束的空字元的位置.
lpBuffer:指向接收字元串的緩存,收到的非空字元串指定了目前目錄的絕對路徑.
DWORD GetModuleFileName(
  HMODULE hModule,
  LPTSTR lpFilename,
  DWORD nSize
);
GetModuleFileName 函數指定目前程序子產品的路徑.它僅僅操作目前程序下的子產品.如果想擷取其他程序下的子產品資訊, 則需使用 GetModuleFileNameEx 函數.Parameters
hModule:子產品的句柄,或者設定為NULL表示目前子產品。
lpFilename:儲存路徑的緩沖區。
nSize:緩沖區的大小。
例子: TCHAR strExePath[_MAX_PATH];
 GetModuleFileName(NULL,strExePath,_MAX_PATH); PathRemoveFileSpec(strExePath);如果目前執行程式的位置為c:\test.exe,GetModuleFileName擷取的strExePath即為c:\test.ext,通過去掉名稱函數最終獲得的strExePath為c:。(注意PathRemoveFileSpec 系統API函數調用時必須包含#include  "Shlwapi.h"作為頭檔案) TCHAR strExePath[_MAX_PATH];
 GetCurrentDirectory(_MAX_PATH, strExePath); 擷取目前的系統目錄,可能是c:也可能是其他值。
 
------------------------------------------------------------------------------------------------------
shlwapi.dll
  shlwapi - shlwapi.dll - DLL檔案資訊
  DLL 檔案: shlwapi 或者 shlwapi.dll
  DLL 名稱: Microsoft Shell Light-weight Utility Library
  描述:   shlwapi.dll是UNC和URL位址動态連結庫檔案,用于注冊鍵值和色彩設定。
  屬于: Microsoft Windows Shell
  系統 DLL檔案: 是
  常見錯誤: File Not Found, Missing File, Exception Errors
  安全等級 (0-5): 0   間諜軟體: 否   廣告軟體: 否
VC中使用GetModuleFileName擷取應用程式路徑

.\\與API函數GetModuleFileName擷取應用程式目錄有何不一樣?
采用.\\也能獲得應用程式目錄,采用GetModuleFileName也能獲得,二者有何不同?
一樣!
一個是相對路徑,一個是絕對路徑
.\\是得到應用程式的目前目錄,但目前目錄不一定等于應用程式執行檔案的所在目錄,一個應用程式被啟動時,目前目錄是可以被任意設定的。
GetModuleFileName()得到子產品的完整路徑名,例如,你載入c:\windows\system32\a.dll,得到子產品句柄h,則你可以用GetModuleFileName()得到h子產品的完整路徑名。
.\\一般用在包含頭檔案的語句中。
另一個是程式編譯後起作用的,例如,打開自定義的配置檔案等。
如何去取得這個Hanlde?
如果你直接用LoadLibrary()或AfxLoadLibrary()載入dll,該函數傳回值就是handle;
如果你隐式載入dll, 用GetModuleHandle("dll檔案名")也可以得到handle;
MFC程式得到本身路徑
在開發工程中,往往需要知道目前程式本身所在目錄。
一種方法是在程式安裝的時候利用安裝程式把檔案路徑寫入系統資料庫。在較大的程式中,這種方法比較常用
另一種,就是在程式得到路徑。這樣,程式随便移動到哪裡,都可以得到正确的路徑。這也是本文介紹的方法。
 
方法一:
[code]
//得到幫助檔案的路徑
CString strFullName = AfxGetApp()->m_pszHelpFilePath;
//得到的是:X:\XXXX\XXX.hlp
//解析路徑,得到目前運作程式所在目錄
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
_splitpath(strAppName, drive, dir, NULL,NULL);
CString strPath;
strPath.Format("%s%s", drive, dir);
//strPath即為得到的目前運作程式所在目錄
[/code]
另外,AfxGetApp()->m_pszAppName 得到應用程式名稱
AfxGetApp()->m_pszExeName 得到程式檔案名,不包括擴充名
 
方法二:
得到全路徑
TCHAR exeFullPath[MAX_PATH]; // MAX_PATH
GetModuleFileName(NULL,exeFullPath,MAX_PATH);//得到程式子產品名稱,全路徑
也就是目前運作程式的全路徑
利用方法一的解析路徑的方法,即可得到程式所在路徑。
GetModuleFileName函數原型
DWORD GetModuleFileName(
   HMODULE hModule,     // handle to module。将要得到的子產品的句柄。如果是目前子產品,NULL
   LPTSTR lpFilename,   // path buffer   得到的檔案名。
   DWORD nSize)          // size of buffer   一般MAX_PATH就可以了      

補充四點:

   1.INI檔案的路徑必須完整,檔案名前面的各級目錄必須存在,否則寫入不成功,該函數傳回 FALSE 值.

   2.檔案名的路徑中必須為 \\ ,因為在VC++中, \\ 才表示一個 \ .

   3.也可将INI檔案放在程式所在目錄,此時 lpFileName 參數為: ".\\student.ini".

   4.從網頁中粘貼源代碼時,最好先粘貼至記事本中,再往VC中粘貼,否則易造成編譯錯誤,開始時我也十分不解,好好的代碼怎麼就不對呢?後來才找到這個方法.還有一些代碼中使用了全角字元如:<,\等,也會

造成編譯錯誤.

INI檔案程式設計

    INI 檔案在系統配置及應用程式參數儲存與設定方面,具有很重要的作用,是以可視化的程式設計一族,如VB、VC、VFP、Delphi等都提供了讀寫INI檔案的方法,其中Delphi中操作INI檔案,最為簡潔,這是因為Delphi3提供了一個TInifile類,使我們可以非常靈活的處理INI檔案。

一、有必要了解INI檔案的結構:

;注釋

[小節名]

關鍵字=值

...

  INI檔案允許有多個小節,每個小節又允許有多個關鍵字, "="後面是該關鍵字的值。

  值的類型有三種:字元串、整型數值和布爾值。其中字元串存貯在INI檔案中時沒有引号,

布爾真值用1表示,布爾假值用0表示。

  注釋以分号";"開頭。

二、定義

  1、在Interface的Uses節增加IniFiles;

  2、在Var變量定義部分增加一行:

myinifile:Tinifile;

  然後,就可以對變量myinifile進行建立、打開、讀取、寫入等操作了。

    Delphi3提供了一個TInifile類下的操作:

三、打開INI檔案

myinifile:=Tinifile.create('program.ini');

   上面這一行語句将會為變量myinifile與具體的檔案 program.ini建立聯系,然後,就可以通過變量myinifile,來讀寫 program.ini檔案中的關鍵字的值了。值得注意的是,如果括号中的檔案名沒有指明路徑的話,那麼這個Program.ini檔案會存儲在 Windows目錄中,把Program.ini檔案存儲在應用程式目前目錄中的方法是:為其指定完整的路徑及檔案名。下面的兩條語句可以完成這個功能:

Filename:=ExtractFilePath(Paramstr(0))+'program.ini';

myinifile:=Tinifile.Create(filename);

四、讀取關鍵字的值

 針對INI檔案支援的字元串、整型數值、布爾值三種資料類型,TINIfiles類提供了三種不同的對象方法來讀取INI檔案中關鍵字的值。

  假設已定義變量vs、vi、vb分别為string、 integer、boolean類型。  

vs:=myinifile.Readstring('小節名','關鍵字',預設值);

vi:=myinifile.Readinteger('小節名','關鍵字',預設值);

vb:=myinifile.Readbool('小節名','關鍵字',預設值);

  其中預設值為該INI檔案不存在該關鍵字時傳回的預設值。

五、寫入INI檔案

  同樣的,TInifile類也提供了三種不同的對象方法,向INI檔案寫入字元串、整型數及布爾類型的關鍵字。  

myinifile.writestring('小節名','關鍵字',變量或字元串值);

myinifile.writeinteger('小節名','關鍵字',變量或整型數值);

myinifile.writebool('小節名','關鍵字',變量或True或False);

  當這個INI檔案不存在時,上面的語句還會自動建立該INI檔案。

六、删除關鍵字

  除了可用寫入方法增加一個關鍵字,Tinifile類還提供了一個删除關鍵字的對象方法:

myinifile.DeleteKey('小節名','關鍵字');

七、小節操作

  增加一個小節可用寫入的方法來完成,删除一個小節可用下面的對象方法:

   myinifile.EraseSection('小節名');

  另外Tinifile類還提供了三種對象方法來對小節進行操作:

  myinifile.readsection('小節名',TStrings變量);可将指定小節中的所有關鍵字名讀取至一個字元串清單變量中;

  myinifile.readsections(TStrings變量);可将INI檔案中所有小節名讀取至一個字元串清單變量中去。

  myinifile.readsectionvalues('小節名',TStrings變量);可将INI檔案中指定小節的所有行(包括關鍵字、=、值)讀取至一個字元串清單變量中去。

八、釋放

在适當的位置用下面的語句釋放myinifile:

myinifile.distory;

九、一個執行個體

   下面用一個簡單的例子(如圖),示範了建立、讀取、存貯INI檔案的方法。myini.ini檔案中包含有"程式參數"小節,和使用者名稱(字元串)、是否正式使用者(布爾值)和已運作時間(整型值)三個關鍵字。程式在窗體建立讀取這些資料,并在窗體釋放時寫myini.ini檔案。

C/C++基本文法學習

STL

C++ primer