概述
在Windows中,不同的訊息由應用程式的不同部分進行處理。MFC庫將很多底層的訊息都禁止了,使用戶更加方便、簡易地處理訊息。例如,用戶接收到諸如移動滑鼠鍵(WM_MOUSEMOVE)訊息或單擊滑鼠鍵(WM_LRBUTTONDOWN)訊息時不必處理視窗和滑鼠的重畫工作,MFC及套用程式框架會替用戶做這些工作。在使用MFC進行編程時,用戶只需處理一些高層的訊息,例如,“用戶在單擊視窗中的OK按扭”,“用戶現在選中了下拉列表框中的第五項”等等,這樣就大大減輕了程式設計師的負擔。一個訊息是由訊息的名稱(UINT)和兩個參數(WPARAM, LPARAM)組成。訊息的參數中包含有重要的信息。例如對滑鼠訊息而言,LPARAM中一般包含滑鼠的位置信息,而WPARAM參數中包含了發生該訊息時,SHIFT、CTRL等鍵的狀態信息,對於不同的訊息類型來說,兩個參數也都相應地具有明確意義。
訊息與輸入焦點
Windows是一個以訊息為導向的系統,應用程式只能被動地等待用戶按鍵的訊息,不能主動地去讀鍵盤的狀態,也就是說,每當鍵盤上有個鍵被按下,系統就會發出一個按鍵訊息給視窗,告訴它某個鍵被按下去了,只要滑鼠移動一下,系統也會發出相應的訊息,並把滑鼠的坐標信息傳給視窗。
Windows可以同時執行許多程式,但鍵盤只有一個,怎么判斷由哪個視窗接收鍵盤及滑鼠的訊息呢?採用“輸入焦點”(inpuut focus)技術可以解決這個問題。只要某個視窗取得輸入焦點,它不但會被提升到螢幕的最前面,顏色也會有所不同,所有的鍵盤訊息就會導向該視窗,該視窗也成為“活動視窗”。
視窗如何取得輸入焦點?通常被滑鼠單擊的視窗會得到輸入焦點,除此之外,程式本身也可以利用SetFocus()來指定哪個視窗擁有輸入焦點。
CWnd* CWnd::SetFocus();
如果調用某視窗的SetFocus()成員函式,該視窗就可以取得輸入焦點,該函式返回前一個擁有輸入焦點的視窗。
如果某個視窗的輸入焦點被搶走,Windows系統就會發出WM_KILLFOCUS訊息給這個失去輸入焦點的視窗,同時還會告訴該視窗下一個取得輸入焦點的視窗的指針。而獲得輸入焦點的視窗則會收到WM_SETFOCUS訊息。
訊息回響函式分別為:
afx_msg void OnKillFocus(CWnd* pNewWnd);
其中的參數為得到輸入焦點的視窗的指針。
Afx_msg void OnSetFocus(CWnd* pOldWnd);
其中的參數為失去輸入焦點的視窗的指針。
訊息的分類
Windows系統預定義了許多訊息,每個訊息都擁有一個宏定義,即用形象的字元串來標識訊息,一系列#define 語句將訊息與特定數值聯繫起來,可以在頭檔案WinUser.h中找到這些宏定義,例如#define WM_PAINT 120
可以在程式中通過訊息名“WM_PAINT”來訪問它。其他訊息如:
#define WM_MOUSEMOVE 0x0200
#define WM_LBUTTONDOWN 0x0201
#define WM_LBUTTONUP 0x0202
#define WM_LBUTTONDBLCLK 0x0203
#define WM_RBUTTONDOWN 0x0204
#define WM_RBUTTONUP 0x0205
#define WM_RBUTTONDBLCLK 0x0206
#define WM_MBUTTONDOWN 0x0207
#define WM_MBUTTONUP 0x0208
#define WM_MBUTTONDBLCLK 0x0209
系統定義的訊息有不同的前綴,不同的前綴有不同的含義。
含義
1. 標準的Windows訊息除了WM_COMMAND訊息,所有以WM_為前綴的訊息都是標準的Windows訊息,如視窗、滑鼠移動、視窗大小改變等,程式啟動或退出甚至每一段固定的時間都會產生標準Windows訊息。如
1) 鍵盤訊息
對於視窗而言,來自用戶的按鍵輸入可分為兩類,一類是系統鍵(system key),另一類則是非系統鍵。凡是ALT和其它鍵一同按下的組合稱為“系統鍵”,視窗收到系統鍵之後,會自動地將它解釋成系統事件,或者查閱鍵盤加速表,將系統鍵翻譯成加速表指定的信息。如:ALT+F4的組合會迫使視窗關閉,“ALT+字母”的組合可能會拉下某個選單。
當用戶按下某個鍵時,Windows系統會先發出WM_KEYDOWN訊息給視窗,這個訊息的意思是“按鍵被壓下去”。接著Windows系統會發出WM_CHAR給同一個視窗,這個訊息代表的意義是“系統送來某個字元”,如果用戶放開此鍵,Windows系統會發出WM_KEYUP訊息,表示“按鍵被放開”。如果用戶一直按住某個鍵不放,經過一段時間之後會產生“連發”的效果,造成Windows系統不停地發出WM_KEYDOWN與WM_CHAR訊息。
計算機內部以ASCII碼的規則來記錄所有的英文字母和數字元號。不過不是鍵盤上每個按鍵都可以對應成ASCII碼中的字元,如大小寫鍵、CTRL鍵、F1到F12鍵等。
每個按鍵都有對應的掃描碼,PC BIOS收到鍵盤的中斷訊息後,會自動將掃描碼翻譯成ASCII碼,但有些控制鍵無法譯成ASCII碼,如Page UP、Page Down等。Windows定義了一套與硬體無關的“虛擬鍵碼”來表示鍵盤上所有的按鍵,如A鍵就是VK_A、ESC鍵就是VK_ESC、F1鍵是VK_F1、ALT鍵是VK_MENU等。因為“虛擬鍵碼”定義的規則與硬體無關,所以有些虛擬鍵在通常的鍵盤上根本就找不著。
#define VK_LBUTTON 0x01
#define VK_RBUTTON 0x02
#define VK_CANCEL 0x03
#define VK_MBUTTON 0x04 /* NOT contiguous with L & RBUTTON */
#define VK_BACK 0x08
#define VK_TAB 0x09
#define VK_CLEAR 0x0C
#define VK_RETURN 0x0D
#define VK_SHIFT 0x10
#define VK_CONTROL 0x11
#define VK_MENU 0x12
#define VK_PAUSE 0x13
#define VK_CAPITAL 0x14
#define VK_F10x70
#define VK_F20x71
#define VK_F30x72
#define VK_F40x73
#define VK_F50x74
#define VK_F60x75
#define VK_F70x76
#define VK_F80x77
#define VK_F90x78
#define VK_F10 0x79
#
#define WM_CHAR0x0102//字元訊息
WM_CHAR也稱為鍵盤訊息,如果某視窗擁有輸入焦點,當用戶在應用程式運行時按下一個鍵時,系統就會產生一個鍵盤訊息WM_CHAR,告訴此視窗鍵盤上哪個鍵被按下了。該訊息的處理函式為Onchar()。具體形式為:
afx_msg void onchar(UINT nChar, UINT nRepCnt, UINT nFlags)
各參數含義為:
nChar: 鍵盤所輸入的ASCII碼。
nRepCnt: 按鍵的重複次數,當用戶按下某個鍵不放時,該參數將持續增加。
nFlag: 用於傳遞按鍵的其它一些信息,如掃描碼,上一次按鍵狀態等。具體如下:
位元組 說明
0-7 鍵盤掃描碼
8 此按鍵為擴充按鍵,如F1,F12等功能鍵,此位元組等於1時為真
9-12 保留
13 此位元組為1表示按下鍵的同時,ALT鍵也被按住了
14 前一個按鍵狀態。此位元組為1代表信息在按鍵被按下之前就送出來了
15 此位元組為1表示這個按鍵已經被放開了,反之就表示還被按著
此外還有兩個常用的鍵盤訊息:WM_KEYDOWN和WM_KEYUP.
WM_KEYDOWN訊息是當用戶按下一個非系統鍵時產生的,非系統鍵就是不按下ALT鍵時的按鍵。
WM_KEYUP 訊息是當用戶釋放一個非系統鍵時產生的。
2) 滑鼠訊息
① #define WM_MOUSEMOVE 0x0200//滑鼠移動訊息
當滑鼠在某個視窗內移動時,Windows會不斷地發出滑鼠移動訊息WM_MOUSEMOVE,並把滑鼠的最新位置傳給該視窗。如果在視窗的範圍內按下滑鼠左鍵,系統就會發出“按下左鍵”的WM_LBUTTONDOWN訊息給該視窗,等到用戶放開按鍵後,再發出“放開左鍵”的WM_LBUTTONUP訊息給該視窗。
滑鼠移動訊息的訊息回響函式為:
afx_msg void OnMouseMove(UINT nFlags, CPoint point)
其中的參數含義如下:
UINT nFlag:此事件發生時,滑鼠按鍵、鍵盤控制鍵的狀態,可以是以下值的任意組合:
當用戶按下CTRL鍵時,nFlags設定為MK_CONTROL。
當用戶按下滑鼠左鍵時,nFlags設定為MK_LBUTTON。
當用戶按下滑鼠中鍵時,nFlags設定為MK_MBUTTON