熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

MFC中動態控件的創建與響應

2013-11-13 10:31:45  來源: .NET編程 

  動態控件是指在需要時由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];  } }

  以上就是動態控件的生成和響應方法各種不同的控件做法略有不同但思路和步驟都是類似的希望以上實例對你能夠有所幫助


From:http://tw.wingwit.com/Article/program/net/201311/13911.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.