MFC中動態添加控件----尋找多年的祕籍,吐血推薦

原文做者tianwaikide

 

動態控件是指在須要時由Create()建立的控件,這與預先在對話框中放置的控件是不一樣的。函數

1、建立動態控件

爲了對照,咱們先來看一下靜態控件的建立。    工具

放置靜態控件時必須先創建一個容器(通常是對話框),這時咱們在對話框編輯窗口中,從工具窗口中拖出所需控件放在對話框中便可,再適當修改控件ID,設置控件屬性,一個靜態控件就建立好了,當對話框被顯示時,其上的控件也會顯示。     動畫

相比之下,靜態控件不須要調用Create()函數來建立。this

而建立動態控件有很大不一樣,如下以按鈕爲例,看一下動態按鈕控件的建立過程:指針

 

1.創建控件ID號:orm

ID號是控件的標識,建立控件前必須先爲它設置一個ID號。對象

打開資源中的「String Table」,在空白行上雙擊鼠標,這時會彈出一個ID屬性對話框,在其中的ID編輯框中輸入ID,如:IDC_MYBUTTON,在Caption中輸入控件標題或註解(注:Caption框不能爲空,爲空會致使建立失敗),這裏我輸入的是按鈕上要顯示的文字--動態按鈕。資源

 

2.創建控件對象:字符串

不一樣種類的控件應建立不一樣的類對象:

·按鈕控件 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_AUTO3STATE 含自動選中狀態的三態複選按鈕
·BS_3STATE 三態複選按鈕,不經常使用
以上風格指定了建立的按鈕類型,不能同時使用,但必須有其一。


(額外風格)
·BS_BITMAP 按鈕上將顯示位圖
·BS_DEFPUSHBUTTON 設置爲默認按鈕,只用於下壓式按鈕,一個對話框中只能指定一個默認按鈕
·rect指定按鈕的大小和位置;
·pParentWnd指示擁有按鈕的父窗口,不能爲NULL;
·nID指定與按鈕關聯的ID號,用上一步建立的ID號。

 

不一樣控件類的Create()函數略有不一樣,可參考相關資料。
例:p_MyBut->Create( "動態按鈕", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, CRect(20,10,80,40), this, IDC_MYBUTTON );
這樣,咱們就在當前對話框中的(20,10)處建立了寬60,高30,按鈕文字爲「動態按鈕」的下壓式按鈕。

爲了使建立過程更方便易用,我定義了以下函數:

CButton* CTextEditorView::NewMyButton(int nID,CRect rect,int nStyle)
{
CString m_Caption;
m_Caption.LoadString( 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_Caption.LoadString( nID )是從字符串表中讀取按鈕文本,這樣在建立按鈕ID時,應該把文本設置好,參數nStyle爲除必須風格外的額外風格。


如下,調用該函數在ONINIATIAL中建立三個按鈕,並指定第一個按鈕爲默認按鈕,按鈕的ID在STRING TABLE中已預先設置好了:

 

//CButton *p_MyBtn[3];//爲了在後面釋放資源,改成在類頭文件中聲明爲公有變量
 p_MyBtn[0]=NewMyButton(ID_MYBTN1,CRect(10,20,60,40),BS_DEFPUSHBUTTON);
 p_MyBtn[1]=NewMyButton(ID_MYBTN2,CRect(10,50,60,70),0);
 p_MyBtn[2]=NewMyButton(ID_MYBTN3,CRect(10,80,60,100),0);

 

2、動態控件的響應

動態控件的響應函數不能用ClassWizard添加,只能手動添加。仍以上面的按鈕爲例,咱們製做按鈕的單擊響應函數。

1.在消息映射表(MESSAGE_MAP)中添加響應函數:

MESSAGE_MAP表中定義了消息響應函數,其格式爲:消息名(ID,函數名),當咱們用ClassWizard添加函數時,會自動添加在AFX_MSG_MAP括起的區間內,如:

 

BEGIN_MESSAGE_MAP(CTextEditorView, CFormView)
//{{AFX_MSG_MAP(CTextEditorView)
ON_BN_CLICKED(IDC_ICONBUT0, OnIconbut0)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


手工添加時不要添加到AFX_MSG_MAP區間內,以防ClassWizard不能正常工做,如:

BEGIN_MESSAGE_MAP(CTextEditorView, CFormView)
//{{AFX_MSG_MAP(CTextEditorView)
ON_BN_CLICKED(IDC_ICONBUT0, OnIconbut0)
//}}AFX_MSG_MAP
ON_BN_CLICKED(ID_MYBTN1, OnMybtn1)
ON_BN_CLICKED(ID_MYBTN2, OnMybtn2)
ON_BN_CLICKED(ID_MYBTN3, OnMybtn3)
END_MESSAGE_MAP()


其中ON_BN_CLICKED是按鈕單擊消息。

2.在頭文件中添加消息響應原函數聲明:

用ClassWizard添加函數時,會在頭文件的AFX_MSG區間內添加函數定義,如:

protected:
//{{AFX_MSG(CTextEditorView)
afx_msg void OnIconbut0();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()


咱們模仿這種形式,只是把函數定義添加到AFX_MSG區間外就好了:

protected:
//{{AFX_MSG(CTextEditorView)
afx_msg void OnIconbut0();
//}}AFX_MSG
afx_msg void OnMybtn1();
afx_msg void OnMybtn2();
afx_msg void OnMybtn3();
DECLARE_MESSAGE_MAP()


3.編寫消息響應函數:

以上是把消息和函數關聯起來了,具體在單擊按鈕後應作的工做在函數中完成:

void CTextEditorView::OnMybtn1()
{
MessageBox( "哈!你單擊了動態按鈕。" );
}
void CTextEditorView::OnMybtn2()
{
……
}
void CTextEditorView::OnMybtn3()
{
……
}


除了按鈕的響應函數外,你還能夠用上面得到的指針訪問按鈕,如:

修改按鈕的大小和位置:p_MyBtn[0]->MoveWindow(……);

修改按鈕文本:p_MyBtn[0]->SetWindowText(……);

顯示/隱藏按鈕:p_MyBtn[0]->ShowWindow(……);等等。

 

3、回收資源

因爲動態控件對象是由new生成的,它不會被程序自動釋放,因此需手工釋放。在控件再也不使用時能夠刪除它,在對話框中的析構函數中銷燬(析構函數沒有手動添加):

CMonthCalCtrlDlg::~CMonthCalCtrlDlg()
{
 for(int i=0;i<3;i++)
 {

     if(p_MyBtn[i])
     delete p_MyBtn[i];

    p_MyBtn[0]=NULL;//若採用其餘方式釋放,則加上這句,不然會出錯
  }

}


以上就是按鈕控件動態生成的方法。  ^_^

 

發佈於CSDN: 2015-05-10

相關文章
相關標籤/搜索