2.14 控件数组典型实例
在设计程序界面时,经常会在对话框中放置多个相同的控件,例如CStatic控件或CEdit控件。如果用户需要同时访问多个控件,例如清空所有编辑框中的文本,采用控件名称逐一进行清空未免有些麻烦。MFC应用程序完全支持控件数组,如果将相同类型的控件放置在控件数组中,那么通过遍历数组中的元素就可以访问每一个控件了。本节将通过几个实例介绍控件数组在应用程序开发中的应用。
实例086 向窗体中动态添加控件
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\02\086
实例说明
在使用标签控件CTabCtrl设计应用程序时,经常需要动态地创建控件,因为在设计期间,无法将其他控件直接放置在CTabCtrl控件上。本实例实现了动态向窗体中添加控件的功能,运行结果如图2.53所示。
图2.53 向窗体中动态添加控件
技术要点
动态创建控件可以分为3 个过程,首先定义一个控件对象,然后调用控件的Create方法创建控件窗口,最后调用ShowWindow方法显示窗口。例如,下面的代码动态创建了一个编辑框,代码如下:
CEdit m_Edit; m_Edit.Create(WS_BORDER,CRect(10,10,50,30),this,0); //创建编辑框控件 m_Edit.ShowWindow(SW_SHOW); //显示控件
由于本实例需要动态创建多个控件,为了方便管理,采用控件数组动态创建控件。定义控件数组与定义普通的数组一样,只是数组类型是控件类型。例如:
CStatic m_statics[6]; CStatic m_static2[6]; CEdit m_edits1[6]; CEdit m_edits2[6];
当创建数组控件窗口时,利用循环就可以了,代码如下:
for ( i = 0; i<6; i++) { pos = m_list1.FindIndex(i); if (pos != NULL) { //创建控件窗口 m_spage1[i].Create(m_list1.GetAt(pos) , WS_CHILD,CRect(20,(i+1)*30+10,100,(i+1)*30+30),&m_tab); //显示控件 m_spage1[i].ShowWindow(SW_SHOW); } m_epage1[i].Create(WS_BORDER,CRect(m_rect.left+100,m_rect.top+(i+1)*30+5, m_rect.left+250,m_rect.top+(i+1)*30+30),this,IDE_EDITCHANGE); m_epage1[i].ShowWindow(SW_SHOW); }
在动态创建控件时,有时还需要处理控件中的各种事件。例如,处理在编辑框文本改变时的事件实现某些功能,可以通过消息映射来处理控件中的各种事件。以编辑框的文本改变的事件为例,首先在对话框中定义一个事件处理函数,并在函数的声明处使用afx_msg关键字,标识该函数是消息处理函数。例如:
afx_msg void OnChangeEdit1();
然后在资源文件中定义一个资源ID,例如:
#define IDE_EDITCHANGE 3201
最后在对话框的消息映射部分添加消息映射宏:
ON_EN_CHANGE(IDE_EDITCHANGE, OnChangeEdit1)
创建编辑框,将编辑框的ID指定为IDE_EDITCHANGE,这样在编辑框的文本发生改变时,会调用OnChangeEdit1消息处理函数。
实现过程
(1)新建一个基于对话框的应用程序。
(2)在对话框中添加CTabCtrl控件。
(3)在对话框类中添加如下成员变量:
CStatic m_statics[6]; //标签1中的静态控件 CStatic m_static2[6]; //标签2中的静态控件 CEdit m_edits1[6]; //标签1中的编辑框 CEdit m_edits2[6]; //标签2中的编辑框 CStatic* m_spage1,*m_spage2; CEdit* m_epage1,*m_epage2; CStringList m_list1,m_list; //记录静态控件文本
(4)在对话框类中添加CreateControl方法,创建控件,代码如下:
void CDynamicCreateDlg::CreateControl() { CRect m_rect; m_tab.GetClientRect(m_rect); m_tab.MapWindowPoints(this,m_rect); POSITION pos=m_list1.GetTailPosition(); int i; for(i=0;i<6;i++) { pos = m_list1.FindIndex(i); if (pos != NULL) { //创建控件窗口 m_spage1[i].Create(m_list1.GetAt(pos) ,WS_CHILD, CRect(20,(i+1)*30+10,100,(i+1)*30+30),&m_tab); //显示控件 m_spage1[i].ShowWindow(SW_SHOW); } m_epage1[i].Create(WS_BORDER,CRect(m_rect.left+100,m_rect.top+(i+1)*30+5, m_rect.left+250,m_rect.top+(i+1)*30+30),this,IDE_EDITCHANGE); //创建控件 m_epage1[i].ShowWindow(SW_SHOW); //显示控件 } for ( i = 0; i<6; i++) { pos = m_list.FindIndex(i); if (pos != NULL) { m_spage2[i].Create(m_list.GetAt(pos) , WS_CHILD,CRect(20,(i+1)*30+10,100,(i+1)*30+30),&m_tab); } m_epage2[i].Create(WS_BORDER,CRect(m_rect.left+100,m_rect.top+(i+1)*30+5, m_rect.left+250,m_rect.top+(i+1)*30+30),this,4554); } }
举一反三
根据本实例,读者可以:
设计共享对话框基类。
实例087 公交线路模拟
这是一个可以提高基础技能的实例
实例位置:光盘\mingrisoft\02\087
实例说明
在开发有关地理定位的应用程序时,程序中经常需要描述各个地点的位置以及交通路线情况。为了清晰、准确地描述某个地点信息,通常采用图形和文字相结合的方式。本实例实现了一个公交线路的模拟程序,利用CStatic控件数组存储各个站点信息,实例运行结果如图2.54所示。
图2.54 公交线路模拟
技术要点
为了简化程序,本实例利用CStatic控件显示图像。在程序中定义一个CStatic类型的控件数组,在程序初始化时调用CStatic的Create方法创建窗口,并指定窗口显示的大小和位置,然后调用SetBitmap方法设置CStatic控件显示的图像。
下面主要介绍一下CStatic的Create方法和SetBitmap方法。
(1)Create方法。该方法用于创建窗口资源,语法如下:
BOOL Create( LPCTSTR lpszText, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID = 0xffff );
参数说明:
● lpszText:用于指定控件显示的文本,本实例中,CStatic控件需要显示位图,所以该参数应该设置为空。
● dwStyle:指定控件风格,如果控件显示位图,该参数需要包含SS_BITMAP风格。
● rect:用于指定控件显示的区域。
● pParentWnd:标识控件的父窗口。
● nID:用于指定控件ID。
(2)SetBitmap方法。该方法用于显示位图信息,语法如下:
HBITMAP SetBitmap( HBITMAP hBitmap );
参数说明:
● hBitmap:绘制的位图句柄,通常可以利用LoadBitmap方法根据程序中导入的位图ID获取位图句柄。
● 返回值:是之前控件关联的位图句柄。如果控件之前没有关联位图,返回值为NULL。
实现过程
(1)新建一个基于对话框的应用程序。
(2)在对话框类中添加CStatic控件数组m_buses。
(3)在对话框类中添加DemoCircuitry方法,创建CStatic控件,并设置CStatic控件显示的位图,代码如下:
void CRutineDemoDlg::DemoCircuitry() { m_buses[0].Create("",WS_CHILD|SS_BITMAP,CRect(40,80,100,140),this); m_buses[1].Create("",WS_CHILD|SS_BITMAP,CRect(180,180,240,240),this); m_buses[2].Create("",WS_CHILD|SS_BITMAP,CRect(350,140,400,380),this); m_buses[3].Create("",WS_CHILD|SS_BITMAP,CRect(460,220,500,400),this); m_buses[4].Create("",WS_CHILD|SS_BITMAP|WS_EX_TRANSPARENT, CRect(580,140,650,160),this); for (int i = 0;i<5;i++) { m_buses[i].SetBitmap(LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1))); m_buses[i].ShowWindow(SW_SHOW); } }
(4)利用属性对话框修改CStatic的属性,使其包含Simple风格。处理对话框的WM_CTLCOLOR消息,使CStatic控件背景透明,使对话框的背景呈白色,代码如下:
HBRUSH CRutineDemoDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr=CDialog::OnCtlColor(pDC,pWnd,nCtlColor); if (nCtlColor==CTLCOLOR_STATIC) //判断是否为CStaitc控件 { pDC->SetBkMode(TRANSPARENT); //设置背景透明 } else { CBrush m_brush(RGB(255,255,255)); //创建白色画刷 CRect m_rect; GetClientRect(m_rect); //获得客户区域 pDC->SelectObject(&m_brush); //选入画刷 pDC->FillRect(m_rect,&m_brush); //使对话框背景为白色 return m_brush; } }
举一反三
根据本实例,读者可以:
设计旅游线路多媒体演示程序。