MFC动态创建CEdit控件

MFC动态创建CEdit控件

原创 2017年12月11日 18:10:04
  • 205

在项目开发时,可能遇到动态创建控件的情况。如根据当前用户的数量,动态创建控件显示用户信息等情况,需要动态常见静态文本框和编辑框等。

此时,利用控件类中Create()函数进行动态创建,默认是显示状态。如:

头文件定义:CStatic *p_MyStatic;

CPP中实现:

p_MyStatic = new CStatic();

p_MyStatic->Create("静态文本框",WS_CHILD|WS_VISIBLE|SS_CENTER,CRect(0,i*perHeight+5,perWidth,(i+1)*perHeight+5),this);

在退出时:

if(pStatic!=NULL)
delete pStatic;

对于单个或者固定数量的控件可以使用指针数组CStatic *p_MyStatic[TOTALCOUTS]照此进行。

但当TOTALCOUTS不固定时,可以使用MFC中CPtrArray进行开发,CPtrArray是一个链表类,用于保存动态创建的控件地址。

实现如下图所示的界面。

MFC动态创建CEdit控件

下面附上具体的代码:

[csharp] view plain copy
  1. // DynamicMultiCtrlsDlg.h : 头文件  
  2. #define EDIT_ID 10000  
  3.   
  4. public:  
  5.     CPtrArray p_MyStatics;  
  6.     CPtrArray p_MyEdits;  

在点击创建时的具体执行代码如下:

[csharp] view plain copy
  1. void CDynamicMultiCtrlsDlg::OnBnClickedBtnCreate()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4.     CString m_staticCaption;  
  5.     CRect rect,rect2;  
  6.     GetClientRect(&rect);  
  7.     GetDlgItem(IDOK)->GetWindowRect(&rect2);  
  8.     ScreenToClient(&rect2);  
  9.   
  10.     int m_counts =21;  
  11.     int perWidth = rect.Width()/4;  
  12.     int perHeight =rect2.top/m_counts;  
  13.     CStatic *p_MyStatic;  
  14.     CEdit *p_MyEdit;  
  15.   
  16.     for(int i=0;i<m_counts;i++)  
  17.     {  
  18.         p_MyStatic = new CStatic();  
  19.         p_MyEdit = new CEdit();  
  20.         m_staticCaption.Format("第%d台IP地址:",i+1);   
  21.         if(i%2==0)  
  22.         {  
  23.             p_MyStatic->Create(m_staticCaption,WS_CHILD|WS_VISIBLE|SS_CENTER,CRect(0,i*perHeight+5,perWidth,(i+1)*perHeight+5),this);  
  24.   
  25.             m_staticCaption.Format("%d台IP",i+1);   
  26.             p_MyEdit->Create(WS_CHILD|WS_VISIBLE|WS_BORDER|SS_CENTER,CRect(perWidth,i*perHeight+5,perWidth*2,(i+1)*perHeight+5),this,EDIT_ID+i);  
  27.             p_MyEdit->SetWindowText(m_staticCaption);  
  28.             if(p_MyStatic!=NULL)  
  29.             {  
  30.                 p_MyStatics.Add((void*)p_MyStatic);  
  31.             //  delete p_MyStatic;  
  32.             }  
  33.             if(p_MyEdit!=NULL)  
  34.             {  
  35.                 p_MyEdits.Add((void*)p_MyEdit);  
  36.             //  delete p_MyEdit;  
  37.             }  
  38.         }else  
  39.         {  
  40.             p_MyStatic->Create(m_staticCaption,WS_CHILD|WS_VISIBLE|SS_CENTER,CRect(perWidth*2,(i-1)*perHeight+5,perWidth*3,i*perHeight+5),this);  
  41.   
  42.             m_staticCaption.Format("%d台IP",i+1);   
  43.             p_MyEdit->Create(WS_CHILD|WS_VISIBLE|WS_BORDER|SS_CENTER,CRect(perWidth*3,(i-1)*perHeight+5,perWidth*4,i*perHeight+5),this,EDIT_ID+i);  
  44.             p_MyEdit->SetWindowText(m_staticCaption);  
  45.             if(p_MyStatic!=NULL)  
  46.             {  
  47.                 p_MyStatics.Add((void*)p_MyStatic);  
  48.                 //delete p_MyStatic;  
  49.             }  
  50.             if(p_MyEdit!=NULL)  
  51.             {  
  52.                 p_MyEdits.Add((void*)p_MyEdit);  
  53.             //  delete p_MyEdit;  
  54.             }  
  55.         }  
  56.     }  
  57. }  
[csharp] view plain copy
  1.   
[csharp] view plain copy
  1. 在有new的时候记得在程序退出时,delete掉所有new的指针  
[csharp] view plain copy
  1.   

[csharp] view plain copy
  1. void CDynamicMultiCtrlsDlg::OnClose()  
  2. {  
  3.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  4.     int n=p_MyStatics.GetSize();  
  5.   for(int i=0;i<n;i++)  
  6.   {  
  7.     CStatic* pStatic=(CStatic*)p_MyStatics.GetAt(i);  
  8. //  pStatic->DestroyWindow();  
  9.     if(pStatic!=NULL)  
  10.         delete pStatic;  
  11.     p_MyStatics[i]=NULL;  
  12.   }  
  13.   p_MyStatics.RemoveAll();  
  14.   n=p_MyEdits.GetSize();  
  15.   for(int i=0;i<n;i++)  
  16.   {  
  17.     CEdit* pEdit=(CEdit*)p_MyEdits.GetAt(i);  
  18.     //pEdit->DestroyWindow();  
  19.     if(pEdit!=NULL)  
  20.         delete pEdit;  
  21.     p_MyEdits[i]=NULL;  
  22.   }  
  23.   p_MyEdits.RemoveAll();  
  24.       
  25.     CDialogEx::OnClose();  
  26. }  
在开发过程中,由于个人基础问题总是担心内存泄漏的问题。所以在new出来的就要delete掉

MFC动态创建CEdit控件

如在1和2的地方,我用了new,所以在总是在3和4的地方要把它们统统delete掉。可是这样导致了创建的控件无法显示。

为什么呢?

因为我把new出来的控件指针delete掉了,能显示出来才奇怪。

但是,不delete掉不会造成内存泄漏吗?

这个我在论坛发帖求助的时候,突然有个这样的理解:new出来的控件地址,已经全部保存到了CPtrArray链表中,而且在程序Close的时候,根据链表中的指针情况,把链表中的指针进行了delete,这也就是等于把new出来的地址给delete掉了。

MFC动态创建CEdit控件

因为Add添加的是控件指针的索引,相当于引用,而不是复制操作,所以只需要delete掉链表中保存的指针即可完成内存的卸载,而不会造成内存的泄漏。

提供VS2010的例程下载地址在这里

在项目开发时,可能遇到动态创建控件的情况。如根据当前用户的数量,动态创建控件显示用户信息等情况,需要动态常见静态文本框和编辑框等。

此时,利用控件类中Create()函数进行动态创建,默认是显示状态。如:

头文件定义:CStatic *p_MyStatic;

CPP中实现:

p_MyStatic = new CStatic();

p_MyStatic->Create("静态文本框",WS_CHILD|WS_VISIBLE|SS_CENTER,CRect(0,i*perHeight+5,perWidth,(i+1)*perHeight+5),this);

在退出时:

if(pStatic!=NULL)
delete pStatic;

对于单个或者固定数量的控件可以使用指针数组CStatic *p_MyStatic[TOTALCOUTS]照此进行。

但当TOTALCOUTS不固定时,可以使用MFC中CPtrArray进行开发,CPtrArray是一个链表类,用于保存动态创建的控件地址。

实现如下图所示的界面。

MFC动态创建CEdit控件

下面附上具体的代码:

[csharp] view plain copy
  1. // DynamicMultiCtrlsDlg.h : 头文件  
  2. #define EDIT_ID 10000  
  3.   
  4. public:  
  5.     CPtrArray p_MyStatics;  
  6.     CPtrArray p_MyEdits;  

在点击创建时的具体执行代码如下:

[csharp] view plain copy
  1. void CDynamicMultiCtrlsDlg::OnBnClickedBtnCreate()  
  2. {  
  3.     // TODO: 在此添加控件通知处理程序代码  
  4.     CString m_staticCaption;  
  5.     CRect rect,rect2;  
  6.     GetClientRect(&rect);  
  7.     GetDlgItem(IDOK)->GetWindowRect(&rect2);  
  8.     ScreenToClient(&rect2);  
  9.   
  10.     int m_counts =21;  
  11.     int perWidth = rect.Width()/4;  
  12.     int perHeight =rect2.top/m_counts;  
  13.     CStatic *p_MyStatic;  
  14.     CEdit *p_MyEdit;  
  15.   
  16.     for(int i=0;i<m_counts;i++)  
  17.     {  
  18.         p_MyStatic = new CStatic();  
  19.         p_MyEdit = new CEdit();  
  20.         m_staticCaption.Format("第%d台IP地址:",i+1);   
  21.         if(i%2==0)  
  22.         {  
  23.             p_MyStatic->Create(m_staticCaption,WS_CHILD|WS_VISIBLE|SS_CENTER,CRect(0,i*perHeight+5,perWidth,(i+1)*perHeight+5),this);  
  24.   
  25.             m_staticCaption.Format("%d台IP",i+1);   
  26.             p_MyEdit->Create(WS_CHILD|WS_VISIBLE|WS_BORDER|SS_CENTER,CRect(perWidth,i*perHeight+5,perWidth*2,(i+1)*perHeight+5),this,EDIT_ID+i);  
  27.             p_MyEdit->SetWindowText(m_staticCaption);  
  28.             if(p_MyStatic!=NULL)  
  29.             {  
  30.                 p_MyStatics.Add((void*)p_MyStatic);  
  31.             //  delete p_MyStatic;  
  32.             }  
  33.             if(p_MyEdit!=NULL)  
  34.             {  
  35.                 p_MyEdits.Add((void*)p_MyEdit);  
  36.             //  delete p_MyEdit;  
  37.             }  
  38.         }else  
  39.         {  
  40.             p_MyStatic->Create(m_staticCaption,WS_CHILD|WS_VISIBLE|SS_CENTER,CRect(perWidth*2,(i-1)*perHeight+5,perWidth*3,i*perHeight+5),this);  
  41.   
  42.             m_staticCaption.Format("%d台IP",i+1);   
  43.             p_MyEdit->Create(WS_CHILD|WS_VISIBLE|WS_BORDER|SS_CENTER,CRect(perWidth*3,(i-1)*perHeight+5,perWidth*4,i*perHeight+5),this,EDIT_ID+i);  
  44.             p_MyEdit->SetWindowText(m_staticCaption);  
  45.             if(p_MyStatic!=NULL)  
  46.             {  
  47.                 p_MyStatics.Add((void*)p_MyStatic);  
  48.                 //delete p_MyStatic;  
  49.             }  
  50.             if(p_MyEdit!=NULL)  
  51.             {  
  52.                 p_MyEdits.Add((void*)p_MyEdit);  
  53.             //  delete p_MyEdit;  
  54.             }  
  55.         }  
  56.     }  
  57. }  
[csharp] view plain copy
  1.   
[csharp] view plain copy
  1. 在有new的时候记得在程序退出时,delete掉所有new的指针  
[csharp] view plain copy
  1.   

[csharp] view plain copy
  1. void CDynamicMultiCtrlsDlg::OnClose()  
  2. {  
  3.     // TODO: 在此添加消息处理程序代码和/或调用默认值  
  4.     int n=p_MyStatics.GetSize();  
  5.   for(int i=0;i<n;i++)  
  6.   {  
  7.     CStatic* pStatic=(CStatic*)p_MyStatics.GetAt(i);  
  8. //  pStatic->DestroyWindow();  
  9.     if(pStatic!=NULL)  
  10.         delete pStatic;  
  11.     p_MyStatics[i]=NULL;  
  12.   }  
  13.   p_MyStatics.RemoveAll();  
  14.   n=p_MyEdits.GetSize();  
  15.   for(int i=0;i<n;i++)  
  16.   {  
  17.     CEdit* pEdit=(CEdit*)p_MyEdits.GetAt(i);  
  18.     //pEdit->DestroyWindow();  
  19.     if(pEdit!=NULL)  
  20.         delete pEdit;  
  21.     p_MyEdits[i]=NULL;  
  22.   }  
  23.   p_MyEdits.RemoveAll();  
  24.       
  25.     CDialogEx::OnClose();  
  26. }  
在开发过程中,由于个人基础问题总是担心内存泄漏的问题。所以在new出来的就要delete掉

MFC动态创建CEdit控件

如在1和2的地方,我用了new,所以在总是在3和4的地方要把它们统统delete掉。可是这样导致了创建的控件无法显示。

为什么呢?

因为我把new出来的控件指针delete掉了,能显示出来才奇怪。

但是,不delete掉不会造成内存泄漏吗?

这个我在论坛发帖求助的时候,突然有个这样的理解:new出来的控件地址,已经全部保存到了CPtrArray链表中,而且在程序Close的时候,根据链表中的指针情况,把链表中的指针进行了delete,这也就是等于把new出来的地址给delete掉了。

MFC动态创建CEdit控件

因为Add添加的是控件指针的索引,相当于引用,而不是复制操作,所以只需要delete掉链表中保存的指针即可完成内存的卸载,而不会造成内存的泄漏。

提供VS2010的例程下载地址在这里