其他分享
首页 > 其他分享> > MFC 操作配置文件INI的方法

MFC 操作配置文件INI的方法

作者:互联网

1. VC中用函数读写ini文件的方法

         ini文件(即Initialization file),这种类型的文件中通常存放的是一个程序的初始化信息。ini文件由若干个节(Section)组成,每个Section由若干键(Key)组成,每个Key可以赋相应的值。读写ini文件实际上就是读写某个的Section中相应的Key的值,而这只要借助几个函数即可完成。

一、向ini文件中写入信息的函数
1. 把信息写入系统的win.ini文件
BOOL WriteProfileString(
      LPCTSTR lpAppName, // 节的名字,是一个以0结束的字符串
      LPCTSTR lpKeyName, // 键的名字,是一个以0结束的字符串。若为NULL,则删除整个节
      LPCTSTR lpString       // 键的值,是一个以0结束的字符串。若为NULL,则删除对应的键
)


2. 把信息写入自己定义的.ini文件
BOOL WritePrivateProfileString(
      LPCTSTR lpAppName,      // 同上
      LPCTSTR lpKeyName,      // 同上
      LPCTSTR lpString,       // 同上
      LPCTSTR lpFileName      // 要写入的文件的文件名。若该ini文件与程序在同一个目录下,也可使用相对
            //路径,否则需要给出绝度路径。
)

如:
::WriteProfileString("Test","id","xym"); 
//在win.ini中创建一个Test节,并在该节中创建一个键id,其值为xym

::WritePrivateProfileString("Test","id","xym","d://vc//Ex1//ex1.ini");
//在Ex1目录下的ex1.ini中创建一个Test节,并在该节中创建一个键id,其值为xym

//若Ex1.ini文件与读写该文件的程序在同一个目录下,则上面语句也可写为:
::WritePrivateProfileString("Test","id","xym",".//ex1.ini");

需要注意的是,C系列的语言中,转义字符'//'表示反斜线'/'。另外,当使用相对路径时,//前的.号不能丢掉了。

二、从ini文件中读取数据的函数
1、从系统的win.ini文件中读取信息
(1) 读取字符串
DWORD GetProfileString(
      LPCTSTR lpAppName,            // 节名
      LPCTSTR lpKeyName,            // 键名,读取该键的值
      LPCTSTR lpDefault,            // 若指定的键不存在,该值作为读取的默认值
      LPTSTR lpReturnedString,      // 一个指向缓冲区的指针,接收读取的字符串
      DWORD nSize                   // 指定lpReturnedString指向的缓冲区的大小
)

如:
CString str;
::GetProfileString("Test","id","Error",str.GetBuffer(20),20);

(2) 读取整数
UINT GetProfileInt(
      LPCTSTR lpAppName,      // 同上
      LPCTSTR lpKeyName,      // 同上
      INT nDefault            // 若指定的键名不存在,该值作为读取的默认值
)

如使用以下语句写入了年龄信息:
::WriteProfileString("Test","age","25"); 
//在win.ini中创建一个Test节,并在该节中创建一个键age,其值为25

则可用以下语句读取age键的值:
int age;
age=::GetProfileInt("Test","age",0);

2、从自己的ini文件中读取信息
(1) 读取字符串
DWORD GetPrivateProfileString(
      LPCTSTR lpAppName,            // 同1(1)
      LPCTSTR lpKeyName,            // 同1(1)
      LPCTSTR lpDefault,            // 同1(1)
      LPTSTR lpReturnedString,      // 同1(1)
      DWORD nSize,                  // 同1(1)
      LPCTSTR lpFileName            // 读取信息的文件名。若该ini文件与程序在同一个目录下,也可使用相      
            //对路径,否则需要给出绝度路径。
)

如:
CString str;
::GetPrivateProfileString("Test","id","Error",str.GetBuffer(20),20,".//ex1.ini");
或:
::GetPrivateProfileString("Test","id","Error",str.GetBuffer(20),20,"d://vc//Ex1//ex1.ini");

(2) 读取整数

UINT GetPrivateProfileInt(
      LPCTSTR lpAppName,      // 同上
      LPCTSTR lpKeyName,      // 同上
      INT nDefault,           // 若指定的键名不存在,该值作为读取的默认值
      LPCTSTR lpFileName      // 同上
)

如使用以下语句写入了年龄信息:
::WritePrivateProfileString("Test","age","25",".//ex1.ini"); 
//在ex1.ini中创建一个Test节,并在该节中创建一个键age,其值为25

则可用以下语句读取age键的值:
int age;
age=::GetPrivateProfileInt("Test","age",0,".//ex1.ini");

三、 删除键值或节

       回顾一下WriteProfileString函数的说明
BOOL WriteProfileString(
      LPCTSTR lpAppName, // 节的名字,是一个以0结束的字符串
      LPCTSTR lpKeyName, // 键的名字,是一个以0结束的字符串。若为NULL,则删除整个节
      LPCTSTR lpString       // 键的值,是一个以0结束的字符串。若为NULL,则删除对应的键
)

       由此可见,要删除某个节,只需要将WriteProfileString第二个参数设为NULL即可。而要删除某个键,则只需要将该函数的第三个参数设为 NULL即可。这是删除系统的win.ini中的节或键,类似的,要删除自己定义的ini文件中的节或键,也可做相同的操作。
       如:
::WriteProfileString("Test",NULL,NULL);      //删除win.ini中的Test节
::WriteProfileString("Test","id",NULL);      //删除win.ini中的id键

::WritePrivateProfileString("Test",NULL,NULL,".//ex1.ini");      //删除ex1.ini中的Test节
::WritePrivateProfileString("Test","id",NULL,".//ex1.ini");      //删除ex1.ini中的id键

四、如何判断一个ini文件中有多少个节
       要判断一个ini文件中有多少个节,最简单的办法就是将所有的节名都找出来,然后统计节名的个数。而要将所有的节名找出来,使用GetPrivateProfileSectionNames函数就可以了,其原型如下:
DWORD GetPrivateProfileSectionNames(
      LPTSTR lpszReturnBuffer,      // 指向一个缓冲区,用来保存返回的所有节名
      DWORD nSize,                  // 参数lpszReturnBuffer的大小
      LPCTSTR lpFileName            // 文件名,若该ini文件与程序在同一个目录下,

                                                //也可使用相对路径,否则需要给出绝度路径
)

下面的是用来统计一个ini文件中共有多少个节的函数,当然,如果需要同时找到每个节中的各个键及其值,根据找到节名就可以很容易的得到了。


/*统计共有多少个节
节名的分离方法:若chSectionNames数组的第一字符是'/0'字符,则表明
有0个节。否则,从chSectionNames数组的第一个字符开始,顺序往后找,
直到找到一个'/0'字符,若该字符的后继字符不是 '/0'字符,则表明前
面的字符组成一个节名。若连续找到两个'/0'字符,则统计结束*/


int CTestDlg::CalcCount(void)
{
TCHAR       chSectionNames[2048]={0};       //所有节名组成的字符数组
char * pSectionName; //保存找到的某个节名字符串的首地址
int i;       //i指向数组chSectionNames的某个位置,从0开始,顺序后移
int j=0;      //j用来保存下一个节名字符串的首地址相对于当前i的位置偏移量
int count=0;      //统计节的个数

//CString name;
//char id[20];
::GetPrivateProfileSectionNames(chSectionNames,2048,".//ex1.ini");   
for(i=0;i<2048;i++,j++)
{
      if(chSectionNames[0]=='/0')
       break;       //如果第一个字符就是0,则说明ini中一个节也没有
      if(chSectionNames[i]=='/0')
      {
       pSectionName=&chSectionNames[i-j]; //找到一个0,则说明从这个字符往前,减掉j个偏移量,
            //就是一个节名的首地址

       j=-1;         //找到一个节名后,j的值要还原,以统计下一个节名地址的偏移量
            //赋成-1是因为节名字符串的最后一个字符0是终止符,不能作为节名

            //的一部分
       /*::GetPrivateProfileString(pSectionName,"id","Error",id,20,".//ex1.ini");
       name.Format("%s",id);*/   
       //在获取节名的时候可以获取该节中键的值,前提是我们知道该节中有哪些键。
   
       AfxMessageBox(pSectionName);      //把找到的显示出来

       if(chSectionNames[i+1]==0)
       {
         break;      //当两个相邻的字符都是0时,则所有的节名都已找到,循环终止
       }
      }   
}
return count;
}

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////

在VC程序中利用系统提供的GetPrivateProfileString及WritePrivateProfileString函数直接读写系统配置ini文件(指定目录下的Ini文件)

假设在当前目录下有一个文件名为Tets.ini的文件
用于保存用户名和密码
文件格式如下:
[Section1]
Item1=huzhifeng
Item2=1234565

1.写INI文件
void CINI_File_TestDlg::OnButtonWrite() 
{
 // TODO: Add your control notification handler code here

 CString strSection       = "Section1";
  CString strSectionKey    = "Item1";
 char strBuff[256];
  CString strValue       = _T("");
 CString strFilePath;

 strFilePath=GetCurrentDirectory(256,strBuff);  //获取当前路径
 strFilePath.Format("%s//Test.ini",strBuff);

 GetDlgItemText(IDC_EDIT_NAME,strValue);     //获取文本框内容:即姓名
 WritePrivateProfileString(strSection,strSectionKey,strValue,strFilePath);  //写入ini文件中相应字段

 strSectionKey="Item2";
 GetDlgItemText(IDC_EDIT_PASSWORD,strValue);   //获取文本框内容:即密码
 WritePrivateProfileString(strSection,strSectionKey,strValue,strFilePath);
}

2.读INI文件内容
void CINI_File_TestDlg::OnButtonRead() 
{
 // TODO: Add your control notification handler code here
 CString strSection       = "Section1";
  CString strSectionKey    = "Item1";
 char strBuff[256];
 CString strValue       = _T("");
 CString strFilePath;

 strFilePath=GetCurrentDirectory(256,strBuff);  //获取当前路径
 strFilePath.Format("%s//Test.ini",strBuff);

 GetPrivateProfileString(strSection,strSectionKey,NULL,strBuff,80,strFilePath); //读取ini文件中相应字段的内容
 strValue=strBuff;
 SetDlgItemText(IDC_EDIT_NAME,strValue);

 strSectionKey="Item2";
 GetPrivateProfileString(strSection,strSectionKey,NULL,strBuff,80,strFilePath);
 strValue=strBuff;
 SetDlgItemText(IDC_EDIT_PASSWORD,strValue);

 UpdateData(FALSE);
}

 

概述  
   
在程序中经常要用到设置或者其他少量数据的存盘,以便程序在下一次执行的时候可以使用,比如说保存本次程序执行时窗口的位置、大小、一些用户设置的数据等等,在   Dos   下编程的时候,我们一般自己产生一个文件,由自己把这些数据写到文件中,然后在下一次执行的时候再读出来使用。在   Win32   编程中当然你也可以这样干,但   Windows   已经为我们提供了两种方便的办法,那就是使用注册表或者   ini   文件(Profile)来保存少量数据。本文中先介绍一下   .ini   文件的使用。  
   
ini   文件是文本文件,中间的数据格式一般为:  
[Section1   Name]  
KeyName1=value1  
KeyName2=value2  
...  
   
[Section2   Name]  
KeyName1=value1  
KeyName2=value2  
   
ini   文件可以分为几个   Section,每个   Section   的名称用   []   括起来,在一个   Section   中,可以有很多的  Key,每一个   Key   可以有一个值并占用一行,格式是   Key=value,Win32   对   ini   文件操作的   api   中,有一部分是对   win.ini   操作的,有一部分是对用户自定义的   ini   文件操作的。Win.in   和   system.ini   是Windows的两个非常重要的初始化文件,Windows将用户所作的选择以及各种变化的系统信息记录在这两个文件中。System.ini   描述了系统硬件的当前状态,Win.ini   文件则包含了Windows   系统运行环境的当前配置。由于   Win.ini   文件的重要性和常用性,Win32   中有专门对   Win.ini   进行操作的   api,它们是:  
   
GetProfileInt   -   从   Win.ini   文件的某个   Section   取得一个   key   的整数值,它的原形是:  
   
GetProfileInt(    
LPCTSTR   lpAppName,   //   指向包含   Section   名称的字符串地址  
LPCTSTR   lpKeyName,   //   指向包含   Key   名称的字符串地址  
INT   nDefault   //   如果   Key   值没有找到,则返回缺省的值是多少  
);    
   
如果   Key   值没有找到的话,返回值是   nDefault   指定的缺省值,如果   Key   中的值是负数,则返回   0,如果  Key   指定的是数字和字符串的混合,则返回数字部分的值,比如说   x=1234abcd,则返回   1234  
   
   
GetProfileString   -   从   Win.ini   文件的某个   Section   取得一个   key   的字符串,它的原形是:  
   
GetProfileString(  
LPCTSTR   lpAppName,   //   指向包含   Section   名称的字符串地址  
LPCTSTR   lpKeyName,   //   指向包含   Key   名称的字符串地址  
LPCTSTR   lpDefault,   //   如果   Key   值没有找到,则返回缺省的字符串的地址  
LPTSTR   lpReturnedString,   //   返回字符串的缓冲区地址  
DWORD   nSize   //   缓冲区的长度  
);    
   
返回的字符串在缓冲区内,返回的   eax   值是返回的字符串的长度(不包括尾部的0)  
   
   
GetProfileSection   -   从   Win.ini   文件中读出整个   Section   的内容,它的原形是:  
   
GetProfileSection(  
LPCTSTR   lpAppName,   //   指向包含   Section   名称的字符串地址  
LPTSTR   lpReturnedString,   //   返回数据的缓冲区地址  
DWORD   nSize   //   返回数据的缓冲区长度  
);    
   
   
WriteProfileSection   -   将一个整个   Section   的值   写入   Win.ini   文件的指定   Section   中,它的原形是:  
   
WriteProfileSection(  
LPCTSTR   lpAppName,   //   指向包含   Section   名称的字符串地址  
LPCTSTR   lpString   //   要写入的数据的地址  
);  
   
如果   Win.ini   没有指定的   Section,API   会新建立一个并写入数据,如果已经存在,则先删除原来   Seciton   中所有的   Key   值然后写入新的。  
   
   
WriteProfileString   -   将一个   Key   值写入   Win.ini   文件的指定   Section   中,它的原形是:  
   
WriteProfileString(    
LPCTSTR   lpAppName,   //   指向包含   Section   名称的字符串地址  
LPCTSTR   lpKeyName,   //   指向包含   Key   名称的字符串地址  
LPCTSTR   lpString   //   要写的字符串地址  
);  
   
如果   Win.ini   没有指定的   Section,API   会新建   Section,如果没有指定的   Key   则新建一个   Key   并写入数据,如果已经存在,则用字符串代替原来的值。    
以上的   Api   是对   Win.ini   操作的,当然对于我们来说,用的更多的是在程序运行的目录中建立自己的   ini   文件,如果需要对自己的   ini   文件操作,就要用到另一组   Api,这一组   api   和上面的很象,只要把上面一组的   Profile  换成   PrivateProfile(私有的)就可以了,参数中也相应的多了一个   ini   文件名的参数。例如  GetPrivateProfileInt、GetPrivateProfileSection、WritePrivateProfileString   等等,   下面分别介绍:  
   
GetPrivateProfileInt   -   从   ini   文件的某个   Section   取得一个   key   的整数值,它的原形是:  
   
GetPrivateProfileInt(    
LPCTSTR   lpAppName,   //   指向包含   Section   名称的字符串地址  
LPCTSTR   lpKeyName,   //   指向包含   Key   名称的字符串地址  
INT   nDefault   //   如果   Key   值没有找到,则返回缺省的值是多少  
LPCTSTR   lpFileName   //   ini   文件的文件名  
);    
   
中间参数和返回值的定义和   GetProfileInt   是一样的。  
   
   
GetPrivateProfileString   -   从   ini   文件的某个   Section   取得一个   key   的字符串,它的原形是:  
   
GetPrivateProfileString(  
LPCTSTR   lpAppName,   //   指向包含   Section   名称的字符串地址  
LPCTSTR   lpKeyName,   //   指向包含   Key   名称的字符串地址  
LPCTSTR   lpDefault,   //   如果   Key   值没有找到,则返回缺省的字符串的地址  
LPTSTR   lpReturnedString,   //   返回字符串的缓冲区地址  
DWORD   nSize   //   缓冲区的长度  
LPCTSTR   lpFileName   //   ini   文件的文件名    
);    
   
   
GetPrivateProfileSection   -   从   ini   文件中读出整个   Section   的内容,它的原形是:  
   
GetPrivateProfileSection(  
LPCTSTR   lpAppName,   //   指向包含   Section   名称的字符串地址  
LPTSTR   lpReturnedString,   //   返回数据的缓冲区地址  
DWORD   nSize   //   返回数据的缓冲区长度  
LPCTSTR   lpFileName   //   ini   文件的文件名    
);    
   
这个   api   可以读出整个   section   的内容,当你不知道   section   中有哪些   key   的时候,可以使用这个   api  将整个   section   读出后再处理。  
   
   
GetPrivateProfileSectionNames   -   从   ini   文件中获得   Section   的名称,它的原形是:  
   
GetPrivateProfileSectionNames(    
LPTSTR   lpszReturnBuffer,   //   返回数据的缓冲区地址  
DWORD   nSize   //   返回数据的缓冲区长度  
LPCTSTR   lpFileName   //   ini   文件的文件名    
);  
   
如果   ini   中有两个   Section:   [sec1]   和   [sec2],则返回的是   'sec1',0,'sec2',0,0   ,当你不知道   ini   中有哪些   section   的时候可以用这个   api   来获取名称  
   
   
WritePrivateProfileSection   -   将一个整个   Section   的内容入   ini   文件的指定   Section   中,它的原形是:  
   
WritePrivateProfileSection(  
LPCTSTR   lpAppName,   //   指向包含   Section   名称的字符串地址  
LPCTSTR   lpString   //   要写入的数据的地址  
LPCTSTR   lpFileName   //   ini   文件的文件名  
);  
   
   
WritePrivateProfileString   -   将一个   Key   值写入   ini   文件的指定   Section   中,它的原形是:  
   
WritePrivateProfileString(    
LPCTSTR   lpAppName,   //   指向包含   Section   名称的字符串地址  
LPCTSTR   lpKeyName,   //   指向包含   Key   名称的字符串地址  
LPCTSTR   lpString   //   要写的字符串地址  
LPCTSTR   lpFileName   //   ini   文件的文件名  
);  
   
如果   ini   中没有指定的   Section,API   会新建   Section,如果没有指定的   Key   则新建一个   Key   并写入数据,如果已经存在,则用字符串代替原来的值。当指定的   ini   也不存在的时候,API   会自动建立一个新的文件,所以使用   ini   的好处是我们不必为了保存少量的数据涉及到文件操作,就连查找文件是否存在的操作都不必要。  
   
使用要点:  
   
在我们实际使用的时候,用的最多的是   GetPrivateProfileString   和   WritePrivateProfileString,但在对自定义  ini   文件操作的时候要注意的是,如果   lpFileName   指定的文件没有路径的话,Api   会去   Windows   的安装目录去找而不会在当前目录找,但是每次用到   ini   函数要获取当前路径显然太麻烦了,这里有一个变通的办法,你只要在  ini   文件名前面加上   .\   就可以了,比如说要对本目录下的   user.ini   操作,那么文件名就是   '.\user.ini'   这样显然比较方便。另外,当你要把一个   Key   清除的时候,可以使用把   lpString   指向一个空的字符串然后使用  WritePrivateProfileString。当你要把一个   section   的全部内容清空的时候,也不必把   key   一个个的清除,可以使用把   lpString   指向一个空的字符串然后使用   WritePrivateProfileSection。

 

VCMFC如何设置对话框背景颜色

1.

重载OnCtlColor    (CDC*    pDC,    CWnd*    pWnd,    UINT    nCtlColor),即WM_CTLCOLOR消息。  
   ----    ①在CExampleDlgDlg的头文件中,添加一CBrush的成员变量:    
   class    CExampleDlgDlg    :    public    CDialog  
   {...  
   protected:  
   CBrush    m_brush;    
   ...  
   };  
   ----    ②在OnInitDialog()函数中添加如下代码:    
   BOOL    CExampleDlgDlg::OnInitDialog()    
   {  
   ...  
   //    TODO:    Add    extra    initialization    here  
   m_brush.CreateSolidBrush(RGB(0,    255,    0));    //    生成一绿色刷子    
   ...  
   }    
   ----    ③利用ClassWizard重载OnCtlColor(…),即WM_CTLCOLOR消息:    
   HBRUSH    CExampleDlgDlg::OnCtlColor  
   (CDC*    pDC,    CWnd*    pWnd,    UINT    nCtlColor)    
   {  
     
   return    m_brush;        //返加绿色刷子  
   }

2.

   修改对话框的OnPaint,在else中添加如下代码  
           CPaintDC    dc(this);  
           CRect    rect;    
           GetClientRect(rect);    
           dc.FillSolidRect(rect,    RGB(0,0,0));    
           CDialog::OnPaint();

3.

在对话框的应用类(App)的.cpp的Initinstance()中加入代码:  
                   //加在int    nResponse=dlg.DoModal();  
                   前一个RGB设置背景色,第二个设置字体颜色  
   SetDialogBkColor(RGB(0,0,255),RGB(0,255,0));

4.

1.在对话框类中添加成员变量:  
   public:  
           CBrush          m_brushBlue;  
   
   2.在对话框类的OnInitDialog()中添加代码:  
   m_brushBlue.CreateSolidBrush(RGB(0,0,255));  
   
   3.用ClassWizard在对话框类中添加成员函数OnCtlCollor(),并在其中添加代码:  
   if(nCtlColor==CTLCOLOR_DLG)  
   return    m_brushBlue;

 

MFC最小化到系统托盘

MFC最小化到系统托盘
--《VC编程知识总结》之一
    在VC++中,想实现将MFC最小化到系统托盘,需要调用NOTIFYICONDATA类,并注册相应的消息,以下详细讲解如何实现:
    第一步,声明一个NOTIFYICONDATA类,也就是NOTIFYICONDATA NotifyIcon;该句可以放在Dlg类的声明中,作为Dlg类的一个成员;也可以放在Dlg类的实现中,作为全局变量来使用。
    第二步,声明一个响应函数afx_msg void OnNotifyIcon(WPARAM wParam,LPARAM IParam);用于响应鼠标操作。将这个函数放入Dlg类的声明中,作为Dlg类的一个成员。
    第三步,定义消息名称以消息号,并注册消息,该步很重要!我就是因为没有注册消息,导致调试了很久都找不到问题所在。该步都是在Dlg.cpp(Dlg的实现中)中操作。定义消息名称和消息号:#define WM_NC (WM_USER+1001),1001只是用于指定一个消息号,可以随便指定。注册则是在BEGIN_MESSAGE_MAP(Dlg,CDialog)和END_MESSAGE_MAP()之间添加ON_MESSAGE(WM_NC,OnNotifyIcon)。
    第四步,在要将MFC最小化到系统托盘的函数中添加如下代码:
    NotifyIcon.cbSize=sizeof(NOTIFYICONDATA);
    NotifyIcon.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    NotifyIcon.hWnd=m_hWnd;
    lstrcpy(NotifyIcon.szTip,"NotifyIcon Test");
    NotifyIcon.uCallbackMessage=WM_NC;
    NotifyIcon.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP;
    Shell_NotifyIcon(NIM_ADD,&NotifyIcon);
    有了上面的代码,当程序运行到含有如上代码的函数时就会在系统托盘处添加一个图标,想隐藏主对话框,就再添加一句ShowWindow(SW_HIDE);这样就实现了将MFC最小化到系统托盘。但还要添加点击托盘图标时响应鼠标的函数,也就是第二步中的函数OnNotifyIcon。
    第五步,OnNotifyIcon函数,如下:
    void CDlg::OnNotifyIcon(WPARAM wParam,LPARAM IParam)
    {
         if ((IParam == WM_LBUTTONDOWN) || (IParam == WM_RBUTTONDOWN))
         {
              ModifyStyleEx(0,WS_EX_TOPMOST);
              ShowWindow(SW_SHOW);
              //Shell_NotifyIcon(NIM_DELETE, &NotifyIcon);
         }
    }
    以上函数写的很简单,因为我定义的是基于对话框的MFC,没有添加menu,所以只是实现了简单的点击托盘图标就弹出主对话框。对于右键点击托盘图标弹出小menu,然后选择操作,最好是建立工程的时候就选择基于菜单的MFC,这样会容易很多,详细的我自己还没有研究,就不乱讲了。对于上面函数中Shell_NotifyIcon(NIM_DELETE,&NotifyIcon)一句,是清除托盘图标,在这里可以没有,但在退出整个程序的时候一定要加上,不然程序退出了,托盘处还有一个图标,只有鼠标指到那里时系统才会发现是进程残留而清除,这种做法很不好!

标签:文件,MFC,配置文件,Section,LPCTSTR,INI,Key,字符串,ini
来源: https://blog.csdn.net/u011555996/article/details/90729459