2008-1-2 孫鑫VC教程學習筆記 NO11.GetStockObject()得到畫筆、畫刷、字型、調色盤的控制代碼,使用時必須用類型轉換。2.什麼是野指標?答:將指標指向的變數的記憶體釋放後,此指標即變成野指標!如何避免野指標?答:將此指標指向NULL即可。p=NULL;3.建立一個完整的視窗的四個步驟SDK,1設計視窗類別,2註冊視窗類別,3建立視窗,4顯示視窗。5 訊息迴圈4.在處理訊息的回呼函數中,我們一定要實現WM_PAINT和WM_DSTROY訊息。前一個訊息用來繪製視窗,後一個訊息在我們關閉視窗時,調用PostQuitMessage這個函數。The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately; the function simply indicates to the system that the thread is requesting to quit at some time in the future. When the thread retrieves the WM_QUIT message from its message queue, it should exit its message loop and return control to the system.5.訊息在windows中是有訊息結構體typedef struct tagMSG { HWND hwnd; //指定訊息所屬視窗的控制代碼 UINT message;//訊息標示符,eg:WM_QUIT這樣的宏 WPARAM wParam; //指定訊息的附加資訊 LPARAM lParam; //指定訊息的附加資訊。具體見不同的訊息說明 DWORD time; //指定訊息產生時間 POINT pt; //指定訊息產生時滑鼠的當前位置} MSG, *PMSG; 訊息佇列:當每一個windows應用程式開始執行時,系統會為它建立一個存放訊息的隊列。Windows將產生的訊息依次放到訊息佇列中,應用程式通過訊息迴圈不斷地從訊息佇列中取出訊息並響應它。進隊訊息和不進隊訊息:進隊訊息有系統放入到應用程式的訊息佇列中,然後由應用程式取出並發送。不進隊訊息在系統調用視窗過程時直接發送給視窗。例如:UpdateWindow就是通過直接將WM_PAINT訊息發送給視窗過程函數來重新整理指定視窗的客戶區。WM_PAINT訊息就不進入此應用程式的訊息佇列 6、WinMain函數int WINAPI WinMain( HINSTANCE hInstance, // handle to current instance HINSTANCE hPrevInstance, // handle to previous instance LPSTR lpCmdLine, // command line int nCmdShow // show state)它是應用程式的人口(實際上是由插入到可執行檔中的啟動代碼調用)。參數解析如下:hInstance:標示應用程式當前啟動並執行執行個體控制代碼。hPrevInstance:標示應用程式當前執行個體的前一個執行個體控制代碼。lpCmdLine:是一個以空結尾的字串,表示傳遞給應用程式的命令列參數。nCmdShow:指示應用程式顯示內容,最大/小化等。一般我們不用管它,它是由程式的調用者來指定。 7、控制代碼:控制代碼是系統返回的標示記憶體中資源(如:cursor、Icon、Brush等)的唯一表示符
8、BOOL GetMessage(
LPMSG lpMsg, // 訊息資訊 HWND hWnd, // 指定接受屬於那一個視窗的資訊,一般設定為NULL,// 用於接受屬於調用線程的所有視窗的資訊 UINT wMsgFilterMin, // 指定擷取訊息的最小值(我們訊息宏都是整數值) UINT wMsgFilterMax // 指定擷取訊息的最大值。如果兩個都為0,則接受// 所有訊息);函數接收到WM_QUIT訊息返回0,其餘的訊息返回非0.錯誤返回-1.由這點我們知道為什麼一定要在銷毀視窗時傳遞WM_QUIT訊息,當接收WM_QUIT訊息時,GetMessage返回0,退出訊息死迴圈,不然windows應用程式就要通過while死迴圈來保證應用程式的運行 9、TranslateMessage函數就是將虛擬鍵訊息轉換為字元訊息,字元訊息被投遞到調用線程的訊息佇列中,當下一次調用GetMessage或PeekMessage時被取出。當我們敲擊鍵盤時,會產生WM_KEYDOWN和WM_KEYUP訊息,這兩個訊息的(wParm、lParam)包含虛擬按鍵碼和掃描碼資訊等,而我們程式要得到的是我們敲擊的鍵的ASCLL碼,TranslateMessage可一將WM_KEYDOWN和WM_KEYUP訊息轉換成一條WM_CHAR訊息(該訊息的wParam參數包含字元鍵的ASCLL碼資訊),並將轉換後的新訊息投遞到調用線程的訊息佇列中。注意在這個過程中TranslateMessage並沒有修改原來的訊息,它指示產生新的訊息並投放到調用線程的訊息佇列中 10、DispatchMessage將訊息回傳給視窗過程函數來處理。 PeekMessage的前4個參數和GetMessage一樣,最後的UINT wRemoveMsg指定訊息回去的方式
| PM_NOREMOVE |
Messages are not removed from the queue after processing by PeekMessage. |
| PM_REMOVE |
Messages are removed from the queue after processing by PeekMessage |
SendMessage是發送不進隊訊息,直接將訊息發送給視窗,並調用視窗的視窗處理函數進行處理,在處理完畢後返回。PostMessage是發送進隊訊息,將訊息發送給相關進程的訊息佇列後立即返回。PostThreadMessage用與想線程發送訊息。 11、WM_PAINT訊息詳解WM_PAINT訊息由系統產生,當一個視窗建立、視窗大小改變(摘抄:Update Region標識了一個視窗上無效、需要被重畫的部分。系統使用它來來產生WM_PAINT訊息。它使應用程式能夠高效地更新視窗內容,因為一方面應用程式可以根據Update Region來決定哪些重畫操作是必要的,哪些是不必要的,從而執行最少的重畫操作;另一方面,即使重畫整個視窗,也只對Update Region區產生效果,其他部分自動處於clip region之外。)應用程式只是強迫接受這個訊息,並在視窗處理函數中進行響應當應用程式訊息佇列為空白時,系統會發送WM_PAINT訊息,應用程式要調用BeginPaint來處理(BeginPaint 和WM_PAINT訊息緊密相關,並且BeginPaint只能在WM_PAINT處理函數中使用)。試一試在WM_PAINT處理函數中不寫BeginPaint會怎樣?程式會像進入了一個死迴圈一樣達到驚人的CPU佔用率,你會發現程式總在處理一個接 一個的WM_PAINT訊息。這是因為在通常情況下,當應用收到WM_PAINT訊息時,視窗的Update Region都是非空的(如果為空白就不需要發送WM_PAINT訊息了),BeginPaint的一個作用就是把該Update Region置為空白,這樣如果不調用BeginPaint,視窗的Update Region就一直不為空白,如前所述,系統就會一直發送WM_PAINT訊息。 12、LOWORD()和HIWORD()宏 分別得到一個32為的字的低位(low-order word)和高位(high-order word)