一直以來對控制項響應事件的內部實現過程沒有乙個清晰的輪廓。今,突然心血來潮想一窺其真面目,查詢了msdn,終於有個清晰的概念。通過用button舉例,現概括如下:
從全域性的角度觀察,在響應事件的全部過程中主要涉及到兩個物件:一事件源,即事件的發生者,也叫事件發布者,就是我們在**中經常見到的sender。二接收者,即事件的響應者,也叫事件訂閱者,就是我們在包含事件響應函式的類。
另外,從事件的發生到事件的響應的處理過程的角度觀察,其中主要包含了以下幾個物件:
一、事件,我們可以設想乙個人可以走路、吃飯、工作。同樣乙個控制項如button,也可以有很多事件,如被點選click,被銷毀dispose,甚至可以被拖動move等等。應該我們可以對button控制項定義click事件、dispose事件和move事件。
二、事件引數,不同的事件有不同的引數,引數能夠更加詳細的說明事件。比如,click事件中可以包含滑鼠點選的座標,move事件中可以包含button被最終放置的座標,甚至我們可以定義button控制項何時被dispose的引數。
三、事件的響應,當點選button時,我們肯定已經知道我們點選button的目的,可能是向資料庫提交資料,可能是關閉視窗,等等。因此,同乙個事件可以有不同的事件響應,也可以有多個事件響應。
四、事件委託,當我們點選button按鈕時,我們想向資料庫提交資料,可是程式卻把我的視窗給關閉了。我們決不希望看到這種張冠李戴的現象,因此我們必須有乙個機制使事件和事件的響應按照我們的意願聯絡起來。而事件委託就是起到了這個作用。
了解了事件過程中涉及到的概念,那麼現在我們來模擬一下事件實現的過程:
1、事件引數
.net中有乙個名為eventargs的類,其表示事件引數資料為空的事件引數類。button控制項的click事件中使用的就是eventargs型別的事件引數。如果我們需要實現的事件必須包含引數,比如button被拖動的move事件,其中包含了button最終被拖到的位置的座標x,y。那麼我們可以從eventargs類派生出子類,包含其中的座標,如:
public moveeventargs:eventargs
public int x
set}
public int y
set}
}以上**就是定義乙個拖動button控制項時的事件引數,其中包含了button控制項被放置螢幕座標。
定義好事件引數後,你可能會想接下來我們是不是應該定義事件了。不是的,根據我的理解(可能我的理解也不正確,但是希望能給你提供乙個思路),最合適的應該先定義事件委託。因為事件委託決定了事件的型別,你可以根據下面的**來驗證:
2、事件委託
對於button控制項的click事件,它的事件委託是.net自帶的型別為eventhandler的事件委託,其定義如下:
public delegate void eventhandler(object sender,eventargs e);
在此事件委託定義中包含了乙個上文提到過的型別為eventargs的物件e,其中不包含任何事件引數,也就是說其值為空。
那麼在move事件中,我們必須包含乙個螢幕座標的事件引數。那麼此事件的事件委託定義如下:
public delegate void moveeventargs(object sender,moveeventargs e);
3、事件
事件委託決定了其可以鏈結的事件的種類,其中的意思可以從一下**中看出:
private event moveeventhandler m_move;
event是系統的關鍵字,它表示m_move是moveeventhandler型別的事件例項。
4、事件響應函式
最後就是事件的響應函式了。事件的響應是在事件的接受者,也就是訂閱者中實現的。因此,事件的響應函式也接收者類中,就如我們經常看到的視窗類form中包含的button1_click(object sender,eventargs e)函式,此函式就是包含有button1控制項的form視窗對button1的點選事件的響應函式。
那麼,我們的move事件的響應函式就應該像button1_move(object sender,moveeventargs e)那樣了。
詳細介紹完事件涉及的物件和實現細節後,我們以button控制項來模擬一下move事件:
//定義moveeventargs事件引數類
public moveeventargs : eventargs
public int x
set}
public int y
set}
}//定義繼承於button的擴充套件的buttonex類,其中包含了move事件
public delegate void moveeventhandler(object sender,moveeventargs e);
public buttonex : button
set}
public void onmove(moveeventargs e)
}//buttonex的舉例
public form1 : form
public form1()
public void button_click(object sender,eventargs e)
public void buttonex1_click(object sender,moveeventargs e)
}總結:
事件的發生由使用者引發或是狀態改變而觸發,在事件發生時取得該事件相應的引數,然後再通過事件委託把事件發布出去。在接收者中訂閱該事件,並在相應的事件處理函式中實現對該事件的響應。
以上文字是本人對事件的理解,如有不當或錯誤之處請指正。非常感謝!
注:以上**為理解基礎上的手寫版,未經除錯,特此說明。
MFC BS GROUPBOX 響應子控制項事件
使用vs2012做專案,需要動態建立多個按鈕,且按鈕都要分組管理。1 首先定義乙個子類mypanel,繼承cbutton 在create時設定按鈕的樣式為bs groupbox,即可定義成乙個容器控制項 2 再定義裡面的按鈕或其他控制項,父控制項指向mypanel,例 ptermitem btnte...
內容頁響應母版頁控制項的事件
內容頁響應母版頁控制項的事件 左直拳在內容頁裡面,如果想響應位於母版頁的控制項的事件,該怎麼辦呢?msdn 開宗明義地告訴我們 對於控制項而言,事件是在本地處理的,即內容頁中的控制項在內容頁中引發事件,母版頁中的控制項在母版頁中引發事件。控制項事件不會從內容頁傳送到母版頁。同樣,也不能在內容頁中處理...
內容頁響應母版頁控制項的事件
內容頁響應母版頁控制項的事件 左直拳在內容頁裡面,如果想響應位於母版頁的控制項的事件,該怎麼辦呢?msdn開宗明義地告訴我們 對於控制項而言,事件是在本地處理的,即內容頁中的控制項在內容頁中引發事件,母版頁中的控制項在母版頁中引發事件。控制項事件不會從內容頁傳送到母版頁。同樣,也不能在內容頁中處理來...