电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

MFC中动态控件的创建与响应


发布日期:2019/1/6
 

动态控件是指在需要时由Create()创建的控件这与预先在对话框中放置的控件是不同的

创建动态控件

为了对照我们先来看一下静态控件的创建放置静态控件时必须先建立一个容器一般是对话框这时我们在对话框编辑窗口中从工具窗口中拖出所需控件放在对话框中即可再适当修改控件ID设置控件属性一个静态控件就创建好了当对话框被显示时其上的控件也会显示静态控件不需要调用Create()函数来创建而创建动态控件有很大不同以下以按钮为例看一下动态控件的创建过程

建立控件ID号

ID号是控件的标识创建控件前必须先为它设置一个ID号打开资源中的String Table在空白行上双击鼠标这时会弹出一个ID属性对话框在其中的ID编辑框中输入IDIDC_MYBUTTON在Caption中输入控件标题或注解(注Caption框不能为空为空会导致创建失败)这里我输入的是按钮上要显示的文字动态按钮

建立控件对象

不同种类的控件应创建不同的类对象

按钮控件 CButton (包括普通按钮单选按钮和复选按钮)

编辑控件 CEdit

静态文本控件 CStatic

标签控件 CTabCtrl

旋转控件 CSpinButtonCtrl

滑标控件 CSliderCtrl

多信息编辑控件 CRichEditCtrl

进度条控件 CProgressCtrl

滚动条控件 CSrcollBar

组合框控件 CComboBox

列表框控件 CListBox

图像列表控件 CImageCtrl

树状控件 CTreeCtrl

动画控件 CAnimateCtrl

本例中我们创建一个CButton类的普通按钮注意不能直接定义CButton对象CButton m_MyBut;这种定义只能用来给静态控件定义控制变量不能用于动态控件

正确做法是用new调用CButton构造函数生成一个实例

CButton *p_MyBut = new CButton(); 然后用CButton类的Create()函数创建该函数原型如下 BOOL Create( LPCTSTR lpszCaption DWORD dwStyle const RECT& rect CWnd* pParentWnd UINT nID );

lpszCaption是按钮上显示的文本

dwStyle指定按钮风格可以是按钮风格与窗口风格的组合取值有窗口风格 WS_CHILD 子窗口必须有 WS_VISIBLE 窗口可见一般都有 WS_DISABLED 禁用窗口创建初始状态为灰色不可用的按钮时使用 WS_TABSTOP 可用Tab键选择 WS_GROUP 成组用于成组的单选按钮中的第一个按钮按钮风格 BS_PUSHBUTTON 下压式按钮也即普通按钮 BS_AUTORADIOBUTTON 含自动选中状态的单选按钮 BS_RADIOBUTTON 单选按钮不常用 BS_AUTOCHECKBOX 含自动选中状态的复选按钮 BS_CHECKBOX 复选按钮不常用 BS_AUTOSTATE 含自动选中状态的三态复选按钮 BS_STATE 三态复选按钮不常用以上风格指定了创建的按钮类型不能同时使用但必须有其一 BS_BITMAP 按钮上将显示位图 BS_DEFPUSHBUTTON 设置为默认按钮只用于下压式按钮一个对话框中只能指定一个默认按钮 rect指定按钮的大小和位置 pParentWnd指示拥有按钮的父窗口不能为NULL nID指定与按钮关联的ID号用上一步创建的ID号不同控件类的Create()函数略有不同可参考相关资料

p_MyBut>Create( 动态按钮 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON CRect() this IDC_MYBUTTON ); 这样我们就在当前对话框中的()处创建了宽按钮文字为动态按钮的下压式按钮

为了使创建过程更方便易用我定义了如下函数 CButton* CTextEditorView::NewMyButton(int nIDCRect rectint nStyle)

{

CString m_Caption; m_CaptionLoadString( nID );

//取按钮标题 CButton *p_Button = new CButton();

ASSERT_VALID(p_Button);

p_Button>Create( m_Caption WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | nStyle rect this nID );

//创建按钮

return p_Button;

}

其中m_CaptionLoadString( nID )是从字符串表中读取按钮文本这样在创建按钮ID时应该把文本设置好参数nStyle为除必须风格外的额外风格以下我调用该函数创建三个按钮并指定第一个按钮为默认按钮按钮的ID已预先设置好了 CButton *p_MyBut[];

p_MyBut[] = NewMyButton( ID_MYBUT CRect() BS_DEFPUSHBUTTON );

p_MyBut[] = NewMyButton( ID_MYBUT CRect() );

p_MyBut[] = NewMyButton( ID_MYBUT CRect() );

动态控件的响应

动态控件的响应函数不能用ClassWizard添加只能手动添加仍以上面的按钮为例我们制作按钮的单击响应函数

在MESSAGE_MAP中添加响应函数

MESSAGE_MAP表中定义了消息响应函数其格式为消息名(ID函数名)当我们用ClassWizard添加函数时会自动添加在AFX_MSG_MAP括起的区间内 BEGIN_MESSAGE_MAP(CTextEditorView CFormView)

//{{AFX_MSG_MAP(CTextEditorView) ON_BN_CLICKED(IDC_ICONBUT OnIconbut) //}}

AFX_MSG_MAP END_MESSAGE_MAP()

手工添加时不要添加到AFX_MSG_MAP区间内以防ClassWizard不能正常工作 BEGIN_MESSAGE_MAP(CTextEditorView CFormView)

//{{AFX_MSG_MAP(CTextEditorView) ON_BN_CLICKED(IDC_ICONBUT OnIconbut) //}}

AFX_MSG_MAP ON_BN_CLICKED(ID_MYBUT OnMybut)

ON_BN_CLICKED(ID_MYBUT OnMybut)

ON_BN_CLICKED(ID_MYBUT OnMybut)

END_MESSAGE_MAP()

其中ON_BN_CLICKED是按钮单击消息

在头文件中添加函数定义

用ClassWizard添加函数时会在头文件的AFX_MSG区间内添加函数定义 protected:

//{{AFX_MSG(CTextEditorView) afx_msg void OnIconbut();//}}

AFX_MSG DECLARE_MESSAGE_MAP()

我们模仿这种形式只是把函数定义添加到AFX_MSG区间外就行了 protected:

//{{AFX_MSG(CTextEditorView) afx_msg void OnIconbut();//}}

AFX_MSG afx_msg void OnMybut();

afx_msg void OnMybut();

afx_msg void OnMybut();

DECLARE_MESSAGE_MAP()

编写消息响应函数

以上是把消息和函数关联起来了具体在单击按钮后应做的工作在函数中完成 void CTextEditorView::OnMybut() { MessageBox( 哈!你单击了动态按钮 ); }

void CTextEditorView::OnMybut() { …… } void CTextEditorView::OnMybut() { …… }

除了按钮的响应函数外你还可以用上面获得的指针访问按钮修改按钮的大小和位置p_MyBut[]>MoveWindow(……); 修改按钮文本p_MyBut[]>SetWindowText(……); 显示/隐藏按钮p_MyBut[]>ShowWindow(……);等等

回收资源

由于动态控件对象是由new生成的它不会被程序自动释放所以需手工释放在控件不再使用时可以删除它 if( p_MyBut[] ) delete p_MyBut[];

以上就是按钮控件动态生成的方法下面再看一下单选按钮的动态生成问题

实例单选按钮组的动态生成

单选按钮也属于CButton类但由于单选按钮总是成组使用的所以它在制作和使用上与普通按钮有一定区别

假设有三个单选按钮组成一组初始时第一个单选按钮处于选中状态

我们先来看静态制作方法在对话框中放置三个单选按钮设置属性如下 Radio属性VisibleGroupTab stopAuto

Radio属性VisibleTab stopAuto

Radio属性VisibleTab stopAuto

这样的属性设置就把三个单选按钮分成了一组它们一次只能有一个被选中若对话框中还有其它成组的单选按钮使用时也会互不干扰但这时还没有使第一个按钮处于选中状态接着就用ClassWizard为这组单选按钮添加变量这里只需为第一个单选按钮添加变量即可设变量名为m_Radio类型选为int型在构造函数中ClassWizard把m_Radio的值设置为我们把它改为这样在运行程序时可以看到第一个单选按钮处于选中状态了之后还应该用ClassWizard为三个单选按钮添加单击响应函数在里面修改m_Radio的值对应三个单选按钮就可以了以上就是通常制作单选按钮组的办法现我们欲改为动态生成主要要解决按钮分组和单击控制问题以下为制作步骤

定义三个单选按钮的ID

打开资源中的String Table在其中添加三个ID值

第一个ID为IDC_MYRADIOCaption为单选

第二个ID为IDC_MYRADIOCaption为单选

第三个ID为IDC_MYRADIOCaption为单选

其中Caption为按钮上要显示的文字可根据需要设置

用CButton类的Create()函数生成三个单选按钮

为方便起见先定义一个函数生成单选按钮 CButton* CTextEditorView::NewMyRadio(int nIDCRect rectint nStyle)

{

CString m_Caption; m_CaptionLoadString( nID );

//取按钮标题 CButton *p_Radio = new CButton();

ASSERT_VALID(p_Radio);

p_Radio>Create( m_Caption WS_CHILD | WS_VISIBLE | nStyle | WS_TABSTOP | BS_AUTORADIOBUTTON rect this nID );

//创建按钮 return p_Radio;

}

函数LoadString()用于从String Table中读取按钮文本Create()函数中设定了单选按钮必须的属性其中就包括了VisibleTab stopAuto属性参数nID为单选按钮ID号rect为单选按钮尺寸nStyle为除必要属性外的其它属性返回值为指向新建按钮的指针

有了这个函数后创建单选按钮组时只要依次调用该函数即可其中单选按钮组的第一个单选按钮必须指定WS_GROUP属性 CButton *p_MyRadio[]; p_MyRadio[] = NewMyRadio( IDC_MYRADIO CRect() WS_GROUP ); p_MyRadio[] = NewMyRadio( IDC_MYRADIO CRect() ); p_MyRadio[] = NewMyRadio( IDC_MYRADIO CRect() );

定义单选按钮组的控制变量设置第一个单选按钮为选中状态

这里不能用ClassWizard添加变量也不要在DoDataExchange()中添加控制变量因为动态控件一开始并不存在在DoDataExchange()中添加控制变量会造成运行错误这里我们只需在头文件中随意定义一个int型变量作为控制变量即可

int m_SelRadio;

在构造函数中设置其初值为m_SelRadio = ;

在上面的创建按钮的语句中用SetCheck()函数设置初始选中的按钮 CButton *p_MyRadio[]; p_MyRadio[] = NewMyRadio( IDC_MYRADIO CRect() WS_GROUP );

p_MyRadio[] = NewMyRadio( IDC_MYRADIO CRect() );

p_MyRadio[] = NewMyRadio( IDC_MYRADIO CRect() );

p_MyRadio[m_SelRadio]>SetCheck();

//设置第一个单选为选中状态

在SetCheck()函数中参数为表示设置为选中状态表示未选中状态

添加鼠标单击响应函数

鼠标单击某单选按钮后其状态已经能自动改变这里我们还需修改控制变量m_SelRadio的值以便跟蹤选中的单选按钮

首先在MESSAGE_MAP中把鼠标单击消息与响应函数联系起来 BEGIN_MESSAGE_MAP(CTextEditorView CFormView)

//{{AFX_MSG_MAP(CTextEditorView) ON_BN_CLICKED(IDC_ICONBUT OnIconbut)

//ClassWizard在此处添加 //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_MYRADIO OnMyRadio)

//单选按钮 ON_BN_CLICKED(IDC_MYRADIO OnMyRadio)

//单选按钮 ON_BN_CLICKED(IDC_MYRADIO OnMyRadio)

//单选按钮 END_MESSAGE_MAP()

然后在头文件的MESSAGE_MAP中定义单击函数

protected:

//{{AFX_MSG(CTextEditorView) afx_msg void OnIconbut();

//ClassWizard在此处添加 //}}AFX_MSG afx_msg void OnMyRadio();

//单选按钮 afx_msg void OnMyRadio();

//单选按钮 afx_msg void OnMyRadio();

//单选按钮 DECLARE_MESSAGE_MAP()

这里注意不要把函数加在AFX_MSG区间内以防影响ClassWizard的使用

定义具体的响应函数(这里是用手工加入的不是用ClassWizard加入的) //单击单选按钮 void CTextEditorView::OnMyRadio() { m_SelRadio=; }

//单击单选按钮 void CTextEditorView::OnMyRadio() { m_SelRadio=; }

//单击单选按钮 void CTextEditorView::OnMyRadio() { m_SelRadio=; }

回收资源

在析构函数中回收创建的单选按钮(也可以在不使用单选按钮时立即回收) CTextEditorView::~CTextEditorView() { int i; for( i=; i<; i++) { if(p_MyRadio[i]) delete p_MyRadio[i]; } }

以上就是动态控件的生成和响应方法各种不同的控件做法略有不同但思路和步骤都是类似的希望以上实例对你能够有所帮助

上一篇:实现静态的TreeView控件导航

下一篇:GetACP的使用方法