消息:主要指由用戶操作而向應(yīng)用程序發(fā)出的信息,也包括操作系統(tǒng)內(nèi)部產(chǎn)生的消息。例如,單擊鼠標(biāo)左按鈕,windows將產(chǎn)WM_LBUTTONDOWN消息,而釋放鼠標(biāo)左按鈕將產(chǎn)生WM_LBUTTONUP消息,按下鍵盤上的字母鍵,將產(chǎn)生WM_CHAR消息。
消息處理:在MFC中,每個專門的處理函數(shù)單獨處理每個消息。消息處理函數(shù)通常是某一類的成員函數(shù),編寫消息處理函數(shù)是編寫框架應(yīng)用程序的主要任務(wù)??梢允褂?/span>ClassWizard創(chuàng)建消息處事函數(shù),然后從Classwizard直接跳到源文件消息處理函數(shù),編寫處理代碼。
消息映射:可以接收消息和命令的所有框架類都有自已的消息映射??蚣芾孟⒂成浒严ⅰ⒚钆c它們的處理函數(shù)鏈接起來。從CCmdTarget類派生的任何類都可以有消息映射。雖然叫作“消息映射”,但消息映射既可以處理消息,也可以處理命令。
與傳統(tǒng)的DOS不同,WINDOWS采用的是基于消息的時間驅(qū)動形式。當(dāng)應(yīng)用程序開始執(zhí)行時,Windows為該程序創(chuàng)建一個“消息隊列(message queue)”,用以存放發(fā)給該程序可能創(chuàng)建的各種不用窗口的消息,消息結(jié)構(gòu)為:
typedef struct tagMSG { // msg
HWND hwnd;//用以標(biāo)識接受消息的窗口的窗口句柄
UINT message;//消息標(biāo)識號
WPARAM wParam;//消息參數(shù)
LPARAM lParam;//消息參數(shù)
DWORD time;//郵寄消息的時間
POINT pt;//在屏幕坐標(biāo)下坐標(biāo)位置
} MSG;
Windows提供了GetMessage、PostMessage、SeekMessge這樣的獲得消息、發(fā)送消息、查找消息的函數(shù),用來處理不同消息來實現(xiàn)程序的目標(biāo)。一條消息一條消息的處理很繁瑣,為了提高效率,MFC將這些消息及函數(shù)封裝起來,這就出現(xiàn)了消息映射表和消息映射宏這樣的概念。
消息映射表:
例如,用戶在按下鼠標(biāo)左鍵時,Windows會發(fā)出WM_LBUTTONDOWN消息。MFC提供了一種消息映射機制將用戶單擊左鍵發(fā)出的WM_LBUTTONDOWN消息和一個函數(shù)聯(lián)系在一起。具體代碼為:
afx_msg void OnLButtonDown(UINT nFlags,CPoint point); //語句的位置在頭文件消息聲明宏(DECLARE_MESSAGE_MAP)內(nèi)
ON_WM_LBUTTONDOWN(); //這條語句的位置是在實現(xiàn)文件的消息宏(BEGIN_MESSAGE_MAP宏和END_MESSAGE_MAP之間)內(nèi)
通過上面兩行代碼已經(jīng)建立了消息的映射,用戶只需要將所要實現(xiàn)功能的代碼寫入下面的函數(shù)內(nèi)即可:
void CDlg::OnLuttonDown(UINT nFlags,CPoint point){
//添加代碼
//CDlg::OnLuttonDown(nFlags,point);
}
MFC中每一個消息都對應(yīng)一個函數(shù),這樣一對一的關(guān)系羅列出來就是一個表,如果開發(fā)人員需要處理某條消息,只要在消息對應(yīng)的處理函數(shù)中寫入代碼即可。
消息映射表在MFC中主要是通過三個宏來實現(xiàn)的。這三個宏分別是:
DECLARE_MESSAGE_MAP消息的聲明宏、
BEGIN_MESSAGE_MAP宏、
END_MESSAGE_MAP宏。
消息映射宏:
消息映射宏主要有命令消息映射宏、控件窗體消息映射宏、普通窗口消息映射宏、用戶自定義消息映射宏。
消息映射宏中有帶有COMMAND字樣的都是用來處理命令消息的。命令消息主要是通過單擊菜單及單擊按鈕產(chǎn)生的。命令消息在CCmdTarget類是沒有處理函數(shù)的,也就是說不在消息映射表內(nèi)。菜單項和按鈕還有其他一些控件都有其ID值,命令消息映射宏主要就是將菜單、按鈕和其他一些控件的ID和處理函數(shù)映射起來。命令消息的添加也是通過MFC的ClassWizard來完的。
在映射宏中有幾個是帶REFLECT字樣的,這些都是用來處理反射消息的映射宏。反射消息是指子控件向父控件發(fā)送消息,而父控件并不處理該消息,而是把消息返回給子控件,讓子控件處理這個消息,這就形成了一去一回的反射過程。反射消息主要是在CladdWizard想到的MessageMap選項卡中,Mesage欄里一些前面帶“=”的消息。
windows消息組成結(jié)構(gòu)
windows消息由消息號和參數(shù)組成:
消息號:windows操作系統(tǒng)通過32整數(shù)標(biāo)識一條windows消息,稱為消息號。windows消息號具有三個特點:
(1)唯一性:唯一性指對于windows操作系統(tǒng)中的每一條消息都有一個且只有一個消息號與它相對應(yīng)。由于windows操作系統(tǒng)通過消息激活相應(yīng)的過程,因此消息的標(biāo)識必須是唯一的。
(2) 直觀性:消息號在形式上表現(xiàn)為消息名,消息名往住直觀地說明了消息的產(chǎn)生方式和類型,例如消息名WM_LBUTTONDOWN直觀地表示了單擊產(chǎn)生的消息。
(3)可自定義性:windows系統(tǒng)定義了一些消息號和消息名,程序員可以運用這些消息,也可以使用自已定義的窗口的消息。形式如下: #define 消息名 消息號
注意,為了不與現(xiàn)有的windows系統(tǒng)消息相沖突,在消息號的定義中通常采用如下:
WM_USER+n WM_USER是windows操作系統(tǒng)定義的用戶消息起始值,程序員必須從該起始值后選取消息號,例如自定義消息名為“MESSAGE_1”和 “MESSAGE_2”,可采用如下形式:
#define MESSAGE_1 WM_USER+1
#DEFINE MESSAGE_2 WM_USER+2
參數(shù):windows的消息具有以下兩個參數(shù):字參數(shù)(wParam);長參數(shù)(lParam)。字參數(shù)和長參數(shù)都是32位整數(shù),用于提供消息的附帶消息,是消息傳遞過程中參數(shù)的載體。附加信息的消息號取決于消息號。
消息種類
消息主要有三種類型,即windows消息,命令消息和控件通知。按消息的產(chǎn)生可以分為四類:
*(1)外界輸入事件產(chǎn)生的消息; *(2)windows系統(tǒng)向應(yīng)用程序發(fā)出的消息
*(3)應(yīng)用程序之間發(fā)送的消息; *(4)其他
根據(jù)產(chǎn)生消息的對象,可以進一步將消息分為以下幾類:
*(1)窗口管理消息 包括激活基本窗口操作的消息,如關(guān)閉、最大化等。
*(2)初始化消息 應(yīng)用程序、窗口、控件等對象初始化的消息。
*(3)輸入消息 包括鍵盤、鼠標(biāo)、繪圖儀等處部輸入工具的輸入消息。
*(4)系統(tǒng)消息 windows系統(tǒng)內(nèi)部消息。
*(5)剪貼板消息 操作剪貼板時產(chǎn)生的消息。
*(6)系統(tǒng)信息消息 用于系統(tǒng)信息發(fā)送和處理的消息。
*(7)控件處理消息 操作控件時產(chǎn)生的消息。
*(8)控件通知消息 系統(tǒng)采用空件通知消息向控件發(fā)送消息。
*(9)滾動條消息 操作滾動條時產(chǎn)生的消息
*(10)非用戶區(qū)消息 非用戶區(qū)產(chǎn)生的消息
*(11)MDI消息 用于多文檔操作的消息
*(12)DDE消息 用于動態(tài)數(shù)據(jù)交換的消息。
*(13)應(yīng)用程序自定義的消息等等。
windows消息:除WM_COMMAND外,所有以WM_開頭的消息都是windows消息。windows消息由窗口和視圖處理。這類消息通常含有用于確定如何對消息進行處理的一些參數(shù)。
控件消息:控件通知包含從控件和其他子窗口傳遞給父窗口的WM_COMMAND通知消息。例如,當(dāng)用戶改變編輯控件中的文本時,編輯控件將發(fā)送給父窗(例如對話框)一條含有EN_EXCHANGE控件通知碼的WM_COMMAND消息。窗口的消息處理函數(shù)將以適當(dāng)?shù)姆绞綄νㄖ⒆鞒鲰憫?yīng),如獲取編輯框中的文本等。像其他標(biāo)準(zhǔn)windows消息一樣,控件通知消息由窗口和視圖進行處理。但是如果用戶單擊控件按鈕時發(fā)出的BN_CLICKED控件通知消息將作為命令消息來處理。
命令消息:命令消息包括來自用戶界面對象的WM_COMMAND通知消息。菜單項、工具欄按鈕和加速鍵都是可以產(chǎn)生命令的用戶界面對象。每個這樣的對象都有一個 ID。通過給對象和命令分配給同一個ID可以把用戶界面對象和命令聯(lián)系起來。命令是被作為特殊的消息來處理的。
通常,命令ID是以其表示的用戶界面對象的功能來命名的。例如,Edit菜單中的Copy命令就可以用ID_EDIT_COPY來表示。MFC類庫預(yù)定義了某些命令ID(如ID_EDIT_PASTE和ID_FILE_OPEN等等)。其他命令ID則要編程人員自已定義,所有預(yù)定義命令ID的列表,參見 AFXRES.H文件。
命令消息的處理和其他消息的處理不同。命令消息可以被更廣泛的對象(如文檔、文檔模板、應(yīng)用程序?qū)ο蟆⒋翱诤鸵晥D等)處理。windows把命令發(fā)送給多個候選對象,稱為命令目標(biāo)。通常其中一個對象有針對該命令的處理函數(shù)。處理函數(shù)處理命令的方法和處理windows消息的方法是一樣的,但調(diào)用機制不一樣。
常用消息
1、WM_LBUTTONDOWN
產(chǎn)生:單擊。
參數(shù):wParam:包含一個整數(shù)值,以標(biāo)識鼠標(biāo)鍵的按下狀態(tài)。鼠標(biāo)的按下標(biāo)識及說明:
MK_LBUTTON 標(biāo)識按下鼠標(biāo)左鍵
MK_MBUTTON 標(biāo)識按下鼠標(biāo)中鍵
MK_RBUTTON 標(biāo)識按下鼠標(biāo)右鍵
lParam:長參數(shù)lParam的低字位包含當(dāng)前坐標(biāo)的x坐標(biāo),在高字節(jié)包含當(dāng)前坐標(biāo)的Y坐標(biāo)。
相似的消息有:WM_LBUTTONUP、WM_RBUTTONDOWN、WM_RBUTTONUP、WM_LBUTTONDBLCLK、WM_RBUTTONDBLCLK
2、WM_KEYDOWN
產(chǎn)生:按下一個非系統(tǒng)鍵的時候產(chǎn)生該事件,系統(tǒng)鍵是指實現(xiàn)系統(tǒng)操作的組合鍵,例如,Alt與某個功能鍵的組合以實現(xiàn)菜單操作等。
參數(shù):wParam:按下鍵的虛擬鍵盤碼,虛擬鍵碼用來標(biāo)識按下或者釋放的是哪個鍵,例如功能鍵F1的虛擬鍵碼在windows.h文件中定義為VK_F1。
lParam:長參數(shù)中記錄了按鍵的重復(fù)次數(shù),掃描碼、轉(zhuǎn)移代碼、先前鍵的狀態(tài)等信息。
相似的消息有WM_KEYUP:放開按下的非系統(tǒng)鍵時產(chǎn)生的事件。
3、WM_CHAR
產(chǎn)生:按一個非系統(tǒng)鍵時產(chǎn)生。
參數(shù):wParam:所按下的鍵的ASCII碼。lParam:長參數(shù)中記錄了按鍵的重復(fù)次數(shù),掃描碼、轉(zhuǎn)移代碼、先前鍵的狀態(tài)等信息。
4、WM_CREATE
產(chǎn)生:由CreateWindow函數(shù)發(fā)出,創(chuàng)建窗口。
參數(shù):wParam:沒用。lParam:包含一個指向CREATESTRUCT數(shù)據(jù)結(jié)構(gòu)的指針,該結(jié)構(gòu)是傳遞給CreateWindow函數(shù)的參數(shù)的副本。
5、WM_CLOSE
產(chǎn)生:當(dāng)關(guān)閉當(dāng)前窗口時產(chǎn)生。
參數(shù):wParam:未用。lParam:未用。
6、WM_DESTROY
產(chǎn)生:當(dāng)窗口要銷毀時由DestroyWindow函數(shù)發(fā)出。
參數(shù):wParam:沒用到。lParam:沒用到。
7、WM_QUIT
產(chǎn)生:退出應(yīng)用程序時由PostQuitMessage函數(shù)發(fā)出。
參數(shù):wParam:含有退出代碼,退出代碼標(biāo)識應(yīng)用程序退出運行時的有關(guān)信息。lParam:未用。
8、WM_COMMAND
產(chǎn)生:用戶與窗口或控件交互時,控件向其窗口發(fā)送WM_COMMAND消息。該消息的wParam參數(shù)的低字節(jié)中包含子窗口(控件)的標(biāo)識值ID,高字節(jié)中包含子窗口向父窗口發(fā)出的通知代碼,lParam參數(shù)中包含控件子窗口句柄。
9、WM_PAINT
用戶改變窗口大小或拖動窗口,系統(tǒng)向應(yīng)用程序發(fā)送WM_PAINT消息,WM_PAINT消息調(diào)用BeginPaint函數(shù)。
消息處理函數(shù)
1、windows消息和控件通知的處理函數(shù)
windows消息和控件通知都是由派生于CWnd的窗口類對象處理的。它們包括CFrameWnd、CMDIFrameWnd、 CMDIChildWnd、CView、CDialog以及從這些派生的用戶自定義的類。這樣的類對象封裝了windows窗口句柄HWND。
windows消息和控件通知都有默認的處理函數(shù),這些函數(shù)在CWnd類中進行了預(yù)定義,MFC類庫以消息名為基礎(chǔ)形成這些處理函數(shù)的名稱,這些處理函數(shù)的名稱都以前綴"On"開始。有的處理函數(shù)不帶參數(shù),有的則有幾個參數(shù);有的還有除void以外的返回值類型。CWnd中消息處理函數(shù)的說明都有 afx_msg前綴。關(guān)鍵字afx_msg用于把處理函數(shù)和其他CWnd成員函數(shù)區(qū)分開來。例如,消息WM_PAINT的處理函數(shù)在CWnd中被聲明成:afx_msg void OnPaint();
windows消息常見的有鼠標(biāo)消息(如WM_LBUTTONDOWN)消息)、鍵盤字符消息(WM_CHAR消息)、鍵盤按鍵消息(WM_KEYDOWN)、窗口重畫消息WM_PAINT,水平和垂直條滾動消息WM_HSCROLL和WM_VSCROLL)以及系統(tǒng)時鐘消息 WM_TIMER等。
2、命令消息的處理函數(shù)
由于用戶界面的對象是用戶自已定義的,每個應(yīng)用程序的用戶界面對象千差萬別,所以對用戶界面對象的命令消息沒有默認的處理函數(shù)。如果某條命令直接影響某個對象,則應(yīng)該讓這個對象來處理這條命令。例如FILE菜單上的Open命令當(dāng)然與應(yīng)用程序有關(guān):應(yīng)用程序打開一個特定的文檔來響應(yīng)該命令。所以,Open 命令的處理函數(shù)是應(yīng)用程序類的一個成員函數(shù)。
把命令消息映射成處理函數(shù)時,ClassWizard以命令ID來命名處理函數(shù),可以接受、修改、或替換推薦使用的名字。例如,Edit菜單項的Cut命令,對應(yīng)ID就是ID_EDIT_CUT,處理函數(shù)被命名成:afx_msg void OnEditCut();
此外,對于控件按鈕的BN_CLICKED通知消息,其處理函數(shù)可以被命名為:
afx_msg void OnClickedUseAsDefault();
命令消息的處理函數(shù)沒有參數(shù)值,也不返回值。
消息映射
用MFC Application Wizard 創(chuàng)建應(yīng)用程序框架時,AppWizard為創(chuàng)建的每個命令目標(biāo)類(包括派生的應(yīng)用程序?qū)ο蟆⑽臋n、視圖、和邊框窗口等)編寫一個消息映射。每個命令目標(biāo)類的消息映射存在相應(yīng)的.cpp文件中??梢栽?/span>AppWizard創(chuàng)建的基本消息映射的基礎(chǔ)上,使用ClassWizard為每個類將處理的消息和命令添加一些條目。例如,對于應(yīng)用程序類,MFC AppWizard創(chuàng)建的基本消息映射為:
BEGIN_MESSAGE_MAP(CTextEditApp,CWinApp)
//{{AFX_MSG_MAP(CTextEditApp)
ON_COMMAND(ID_APP_ABOUT,OnAppAbout)
//注:ClassWizard將在此處添加和刪除消息映射宏
//不要編輯這些生成的代碼塊
//}}AFX_MSG_MAP
//基于標(biāo)準(zhǔn)文件的文檔命令(新建和打開)
ON_COMMAND(ID_FILE_NEW,CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN,CWinApp::OnFileOpen)
//標(biāo)準(zhǔn)的打印設(shè)置命令
ON_COMMAND(ID_FILE_PRINT_SETUP,CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
聯(lián)系客服