【SunXin.VC++深入】
1.窗口(Windows)和句柄(HANDLE,handle):窗口句柄(HWND)圖標句柄(HICON)、光標句柄(HCURSOR)和畫刷句柄(HBRUSH)
2.消息,消息隊列,消息循環,消息響應
.OS將操作包裝成Message
.typedef struct MSG {
HWND hwnd; //窗口句柄,即標示消息所屬的窗口
UINT message;//標示消息的類別,是鼠標還是鍵盤等 如鼠標左鍵按下消息是WM_LBUTTONDOWN,鍵盤按下消息是WM_KEYDOWN,字符消息是WM_CHAR
WPARAM wParam;//消息的附加信息
LPARAM lParam;//消息的附加信息
DWORD time;//消息投遞到消息隊列中的時間
POINT pt;//鼠標的當前位置
} MSG;
.消息隊列,每一個Windows應用程序開始執行后,系統都會為該程序創建一個消息隊列,這個消息隊列用來存放該程序創建的窗口的消息
.進隊消息(OS將產生的消息放在應用程序的消息隊列中,讓應用程序來處理)
不進隊消息(OS直接調用窗口的處理過程)
.Windows應用程序的消息處理機制
while(GetMessage(&msg,NULL,0,0)){//接收到WM_QUIT消息時,才返回0
TranslateMessage(&msg);//對消息進行包裝處理然后再以消息的形式投放到消息隊列
DispatchMessage(&msg);//消息回傳給操作系統,由操作系統調用窗口過程函數對消息進行處理
}
(1)操作系統接收到應用程序的窗口消息,將消息投遞到該應用程序的消息隊列中。
(2)應用程序在消息循環中調用GetMessage函數從消息隊列中取出一條條的消息。取出后,以對消息進行一些預處理,如放棄對某些消息的響應,或者調用TranslateMessage產生新的消息
(3)應用程序調用DispatchMessage,將消息回傳給操作系統。消息是由MSG結構體對象來表示的,其中就包含了接收消息的窗口的句柄。因此,DispatchMessage函數總能進行正確的傳遞。(4)系統利用WNDCLASS結構體的lpfnWndProc成員保存的窗口過程函數的指針調用窗口過程,對消息進行處理(即“系統給應用程序發送了消息”)。
.窗口過程函數
lresult callback windowproc(
hwnd hwnd, // 對應消息的窗口句柄
uint umsg, // 消息代碼,區別消息的類型
wparam wparam, // 消息代碼的附加參數1
lparam lparam // 消息代碼的附加參數2
);
【蔡學鏞.揭開消息循環的神秘面紗】
簡單歸納如下:
訊息循環被封裝進了 Application 類別的 Run() 靜態方法中;Windows Procedure 被封裝進了 NativeWindow 與 Control 類別中;
個別的訊息處理動作被封裝進 Control 類別的 OnXyz()(例如 OnPaint())。我們可以覆蓋(override)OnXyz(),來提供我們自己的程序。
也可以利用.NET的事件(event)機制,在 Xyz 事件上,加入我們的事件處理函式(Event Handler)。Control 類別的 OnXyz() 會主動呼叫 Xyz 事件的處理函式。
請注意,因為 Xyz 的事件處理函式是由 Control 類別的 OnXyz() 方法所呼叫的,所以當你覆寫 OnXyz() 方法時,
不要忘了呼叫 Control 類別的 OnXyz()(除非你有特殊需求),否則 Xyz 事件處理函式將會沒有作用。
只要呼叫 base.OnXyz(),就可以呼叫到 Control 類別的 OnXyz() 方法
1. 在 Main() 中,利用 Application.Run() 來將 Form1 窗口顯示出來,并進入訊息循環。程序的執行過程中,Application.Run() 一直未結束。
2. OS 在此 Process 的訊息隊列內放進一個 WM_PAINT 訊息,好讓窗口被顯示出來。
3. WM_PAINT 被 Application.Run() 內的訊息循環取出來,發派到 WndProc()。由于多型(Polymorphism)的因素,此次調用(invoke)到的 WndProc() 是屬于 Form1 的 WndProc(),也就是上述程序中批注(comment)1 的地方,而不是調用到 Control.WndProc()。
4. 在 Form1.WndProc() 的最后,有調用 base.WndProc(),這實際上調用到 Control.WndProc()。
5. Control.WndProc() 從 Message 參數中得知此訊息是 WM_PAINT,于是調用 OnPaint()。由于多型的因素,此次調用到的 OnPaint() 是屬于 Form1 的 OnPaint(),也就是上述程序中批注 2 的地方,而不是調用到 Control.OnPaint()。
6. 在 Form1.OnPaint() 的最后,有調用 base.OnPaint(),這實際上調用到 Control.OnPaint()。
7. 我們曾經在 Form1 的建構式(constructor)中將 Form1_Paint() 與 Form1_Paint2() 登記成為 Paint 事件處理函式(Event Handler)。Control.OnPaint() 會去依序去呼叫這兩個函式,也就是上述程序中批注 3 與 4 的地方。
【.NET Windows Message】
1.Control--Button,Form……
protect vitrual WndProcess(ref Message);
調用private Wm_(ref Message);//具體某類消息
調用Oprotect virtual On_xx(EventArg e);//觸發相關事件
2.解釋事件冒泡:比如鍵盤消息可先由Form來處理,然后交由相關的Control來處理
3.解釋FormPaint:窗口的移動,最小化,最大話都會引起窗口內容的重新Paint,OS產生一個相關消息發給應用程序的消息隊列,應用程序得到并處理消息時先是Form依次經過Wn_Process,Wn_..,On_Paint,Form_Paint,之后Form中的每一個Control也會依次做重繪的工作