一、什麼是Windows訊息迴圈
- 概念介紹
- 在 Windows 作業系統中,訊息迴圈是應用程式處理訊息的核心機制。訊息是 Windows 應用程式與作業系統以及應用程式內部不同元件之間通訊的基本單元。這些訊息可以是由使用者操作產生的,如滑鼠點選、鍵盤按鍵;也可以是系統內部產生的,如視窗大小改變、定時器事件等。
- 訊息佇列
- 訊息首先被放入訊息佇列。訊息佇列是一個先進先出(FIFO)的資料結構。當使用者進行操作(如按下滑鼠左鍵)時,作業系統會把相應的訊息(例如 WM_LBUTTONDOWN 訊息,表示滑鼠左鍵按下)放入應用程式的訊息佇列中。
- 應用程式有兩種型別的訊息佇列:系統訊息佇列和應用程式訊息佇列。系統訊息佇列接收來自硬體裝置(如鍵盤、滑鼠)的訊息,然後將這些訊息分發給對應的應用程式訊息佇列。
- 訊息迴圈的工作流程
- 應用程式通常會在一個主函式(如 WinMain)中啟動訊息迴圈。訊息迴圈的基本結構是一個迴圈體,不斷地從訊息佇列中獲取訊息並進行處理。
- 典型的訊息迴圈程式碼如下(以 C++ 和 Win32 API 為例):
while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
首先是GetMessage
函式,它從應用程式訊息佇列中獲取一條訊息,並將訊息的資訊填充到MSG
結構(msg
變數)中。如果獲取到的訊息是WM_QUIT
訊息(表示應用程式要退出),GetMessage
函式返回0
,訊息迴圈結束。
接著TranslateMessage
函式用於處理鍵盤訊息,將按鍵訊息轉換為字元訊息。例如,當使用者按下並釋放一個按鍵時,它會生成相應的字元訊息(如果按鍵對應的是可列印字元),這樣應用程式可以直接處理字元輸入,而不是複雜的按鍵掃描碼。 最後DispatchMessage
函式將訊息分發給視窗過程(WndProc
)函式進行處理。視窗過程函式是一個自定義的函式,用於處理特定視窗接收到的訊息。不同的視窗可以有不同的視窗過程函式,根據訊息的型別(如WM_PAINT
用於重繪視窗、WM_COMMAND
用於處理選單和按鈕等控制元件的命令訊息),視窗過程函式會執行相應的操作來響應訊息。
- 視窗過程函式(WndProc)
- 視窗過程函式是訊息迴圈機制的關鍵部分。它接收訊息、訊息的引數(如滑鼠位置、按鍵的虛擬鍵碼等),並根據訊息型別執行相應的操作。
- 例如,對於
WM_PAINT
訊息,視窗過程函式可能會呼叫繪圖函式來繪製視窗的內容;對於WM_DESTROY
訊息,它可能會進行一些清理工作,併傳送WM_QUIT
訊息來結束應用程式的訊息迴圈。 - 一個簡單的視窗過程函式示例如下:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); // 在這裡進行繪圖操作 EndPaint(hWnd, &ps); break; } case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
- 重要性和應用場景
- 訊息迴圈使得 Windows 應用程式能夠以事件驅動的方式執行。它允許應用程式在等待使用者輸入或其他事件的同時,不會佔用過多的系統資源。因為應用程式在沒有訊息需要處理時,會處於一種等待狀態,直到有新的訊息進入訊息佇列。
- 這種機制廣泛應用於各種 Windows 桌面應用程式的開發中,無論是簡單的工具軟體還是複雜的圖形介面應用程式,都依賴訊息迴圈來處理使用者互動和系統事件。
二、windows下點選一個按鈕,經歷了哪些?
- 硬體層面訊息產生
- 當使用者點選滑鼠按鈕時,滑鼠硬體會檢測到這個物理動作。滑鼠會將這個動作轉換為電訊號,透過介面(如 USB 介面)傳送給計算機的硬體中斷系統。這個訊號包含了滑鼠按鍵按下的基本資訊,如按下的是左鍵、右鍵還是中鍵等。
- 系統訊息佇列接收訊息
- 計算機的硬體中斷系統會將滑鼠點選產生的訊號傳遞給作業系統核心。作業系統核心會將這個滑鼠點選事件包裝成一個訊息,放入系統訊息佇列。這個訊息的型別可能是
WM_LBUTTONDOWN
(滑鼠左鍵按下)、WM_RBUTTONDOWN
(滑鼠右鍵按下)等,具體取決於按下的是哪個滑鼠按鍵。系統訊息佇列會按照訊息產生的先後順序來排列這些訊息。
- 計算機的硬體中斷系統會將滑鼠點選產生的訊號傳遞給作業系統核心。作業系統核心會將這個滑鼠點選事件包裝成一個訊息,放入系統訊息佇列。這個訊息的型別可能是
- 訊息分發到應用程式訊息佇列
- 作業系統會從系統訊息佇列中取出滑鼠點選訊息,並根據當前滑鼠指標所在的位置等因素,確定該訊息應該傳送到哪個應用程式的訊息佇列。如果滑鼠指標位於某個應用程式的視窗(包括視窗內的按鈕)之上,作業系統就會將滑鼠點選訊息傳送到該應用程式的訊息佇列。這個過程涉及到視窗管理和訊息路由機制,作業系統會根據視窗的層次結構、可見性以及焦點狀態等因素來準確地分發訊息。
- 應用程式訊息迴圈獲取訊息
- 應用程式在其主函式(如 WinMain)中的訊息迴圈開始工作。訊息迴圈會不斷地呼叫
GetMessage
函式從應用程式訊息佇列中獲取訊息。當獲取到滑鼠點選相關的訊息(如WM_LBUTTONDOWN
)後,訊息迴圈會繼續執行後續步驟來處理這個訊息。
- 應用程式在其主函式(如 WinMain)中的訊息迴圈開始工作。訊息迴圈會不斷地呼叫
- 訊息預處理(TranslateMessage)
- 在獲取訊息後,應用程式會呼叫
TranslateMessage
函式。對於滑鼠點選訊息來說,這個函式可能不會對其進行太多實質性的改變,但如果涉及到組合鍵(例如 Ctrl + 滑鼠點選等)或者其他需要轉換的情況,它會進行相應的處理。在簡單的滑鼠點選按鈕場景下,這個函式主要是按照標準的訊息處理流程來傳遞訊息。
- 在獲取訊息後,應用程式會呼叫
- 訊息分發到視窗過程函式(DispatchMessage)
- 接著,
DispatchMessage
函式會將滑鼠點選訊息傳送到對應的視窗過程函式(WndProc
)。視窗過程函式是應用程式中用於處理特定視窗訊息的函式。每個視窗通常都有自己的視窗過程函式來處理傳送到該視窗的訊息。
- 接著,
- 視窗過程函式處理訊息
- 在視窗過程函式中,會有一個
switch
語句(或類似的訊息處理結構)來根據訊息的型別進行處理。當收到滑鼠點選按鈕相關的訊息(如WM_LBUTTONDOWN
)時,會檢查點選位置是否在按鈕的區域內。如果在按鈕區域內,會觸發按鈕對應的操作,可能包括髮送自定義的命令訊息(如WM_COMMAND
)來通知應用程式的其他部分按鈕被點選了,然後執行按鈕被按下後的邏輯,如改變按鈕的外觀(按下狀態的視覺效果),並呼叫相關的函式來完成按鈕點選後應該執行的功能,如開啟一個新視窗、儲存檔案等操作。最後,當滑鼠按鍵被釋放時,還會產生WM_LBUTTONUP
訊息,經過類似的訊息傳遞和處理過程,按鈕會恢復到未按下的外觀狀態。
- 在視窗過程函式中,會有一個
三、是否每個程式都有自己的訊息迴圈
- 硬體層面訊息產生
- 當使用者點選滑鼠按鈕時,滑鼠硬體會檢測到這個物理動作。滑鼠會將這個動作轉換為電訊號,透過介面(如 USB 介面)傳送給計算機的硬體中斷系統。這個訊號包含了滑鼠按鍵按下的基本資訊,如按下的是左鍵、右鍵還是中鍵等。
- 系統訊息佇列接收訊息
- 計算機的硬體中斷系統會將滑鼠點選產生的訊號傳遞給作業系統核心。作業系統核心會將這個滑鼠點選事件包裝成一個訊息,放入系統訊息佇列。這個訊息的型別可能是
WM_LBUTTONDOWN
(滑鼠左鍵按下)、WM_RBUTTONDOWN
(滑鼠右鍵按下)等,具體取決於按下的是哪個滑鼠按鍵。系統訊息佇列會按照訊息產生的先後順序來排列這些訊息。
- 計算機的硬體中斷系統會將滑鼠點選產生的訊號傳遞給作業系統核心。作業系統核心會將這個滑鼠點選事件包裝成一個訊息,放入系統訊息佇列。這個訊息的型別可能是
- 訊息分發到應用程式訊息佇列
- 作業系統會從系統訊息佇列中取出滑鼠點選訊息,並根據當前滑鼠指標所在的位置等因素,確定該訊息應該傳送到哪個應用程式的訊息佇列。如果滑鼠指標位於某個應用程式的視窗(包括視窗內的按鈕)之上,作業系統就會將滑鼠點選訊息傳送到該應用程式的訊息佇列。這個過程涉及到視窗管理和訊息路由機制,作業系統會根據視窗的層次結構、可見性以及焦點狀態等因素來準確地分發訊息。
- 應用程式訊息迴圈獲取訊息
- 應用程式在其主函式(如 WinMain)中的訊息迴圈開始工作。訊息迴圈會不斷地呼叫
GetMessage
函式從應用程式訊息佇列中獲取訊息。當獲取到滑鼠點選相關的訊息(如WM_LBUTTONDOWN
)後,訊息迴圈會繼續執行後續步驟來處理這個訊息。
- 應用程式在其主函式(如 WinMain)中的訊息迴圈開始工作。訊息迴圈會不斷地呼叫
- 訊息預處理(TranslateMessage)
- 在獲取訊息後,應用程式會呼叫
TranslateMessage
函式。對於滑鼠點選訊息來說,這個函式可能不會對其進行太多實質性的改變,但如果涉及到組合鍵(例如 Ctrl + 滑鼠點選等)或者其他需要轉換的情況,它會進行相應的處理。在簡單的滑鼠點選按鈕場景下,這個函式主要是按照標準的訊息處理流程來傳遞訊息。
- 在獲取訊息後,應用程式會呼叫
- 訊息分發到視窗過程函式(DispatchMessage)
- 接著,
DispatchMessage
函式會將滑鼠點選訊息傳送到對應的視窗過程函式(WndProc
)。視窗過程函式是應用程式中用於處理特定視窗訊息的函式。每個視窗通常都有自己的視窗過程函式來處理傳送到該視窗的訊息。
- 接著,
- 視窗過程函式處理訊息
- 在視窗過程函式中,會有一個
switch
語句(或類似的訊息處理結構)來根據訊息的型別進行處理。當收到滑鼠點選按鈕相關的訊息(如WM_LBUTTONDOWN
)時,會檢查點選位置是否在按鈕的區域內。如果在按鈕區域內,會觸發按鈕對應的操作,可能包括髮送自定義的命令訊息(如WM_COMMAND
)來通知應用程式的其他部分按鈕被點選了,然後執行按鈕被按下後的邏輯,如改變按鈕的外觀(按下狀態的視覺效果),並呼叫相關的函式來完成按鈕點選後應該執行的功能,如開啟一個新視窗、儲存檔案等操作。最後,當滑鼠按鍵被釋放時,還會產生WM_LBUTTONUP
訊息,經過類似的訊息傳遞和處理過程,按鈕會恢復到未按下的外觀狀態。
- 在視窗過程函式中,會有一個
三、命令列程式的訊息迴圈
- 多數簡單命令列應用程式沒有訊息迴圈
- 大部分簡單的命令列應用程式確實沒有訊息迴圈。這類應用程式的主要目的是執行特定的命令任務,例如一個簡單的檔案複製命令列工具。它接收使用者在命令列輸入的引數(如原始檔路徑和目標檔案路徑),執行檔案複製操作,然後退出。
- 這些應用程式通常是按照線性的流程執行:從命令列讀取引數,執行相應的操作(如計算、檔案處理等),最後輸出結果。它們不涉及處理圖形介面的訊息,如滑鼠點選、視窗重繪等,所以不需要訊息迴圈來處理這類訊息。
- 命令列應用程式中可能存在訊息迴圈的情況
- 需要長時間執行並監控外部事件的命令列應用程式
- 有些命令列應用程式需要長時間執行並等待特定事件。例如,一個命令列的網路監控工具,它需要持續監測網路介面的資料流量。在這種情況下,雖然沒有圖形介面訊息需要處理,但它可能會利用類似於訊息迴圈的機制來等待和處理網路事件。
- 它可能會使用作業系統提供的非同步事件通知機制(如在 Linux 系統中使用
select
、poll
或epoll
等函式,在 Windows 系統中使用WSAAsyncSelect
或WSAEventSelect
等函式)。這些機制可以看作是一種特殊的 “訊息迴圈”,用於等待特定的事件(如網路資料到達、網路連線斷開等),當事件發生時,執行相應的處理操作。
- 具有簡單圖形介面元件的命令列應用程式
- 當命令列應用程式包含一些簡單的圖形介面元素時,例如一個帶有進度條顯示的命令列下載工具。為了更新進度條的狀態(這涉及到圖形介面的更新),它可能需要處理視窗訊息,這時就需要某種形式的訊息迴圈。
- 這種情況下,應用程式可能會在後臺執行一個簡單的訊息迴圈來處理圖形介面相關的訊息,同時在前臺繼續執行主要的命令列任務(如檔案下載),並根據下載進度更新圖形介面元素。
- 需要長時間執行並監控外部事件的命令列應用程式
四、訊息迴圈的管理
- GetMessage 函式的基本原理
GetMessage
函式主要用於從呼叫執行緒的訊息佇列中獲取訊息。在 Windows 作業系統中,每個執行緒都可以有自己的訊息佇列。當一個應用程式有多個視窗或者執行緒時,訊息佇列的管理就變得很重要。- 對於一個普通的單執行緒、單視窗應用程式,
GetMessage
函式獲取的是與該應用程式視窗相關的訊息。這些訊息包括使用者操作產生的訊息(如滑鼠點選、鍵盤按鍵),以及系統產生的訊息(如視窗大小改變、定時器訊息等)。
- 獲取自身訊息的情況
- 在大多數簡單應用程式場景下,
GetMessage
函式獲取的訊息主要是針對應用程式自身視窗的訊息。例如,一個只有一個主視窗的應用程式,GetMessage
函式會獲取這個主視窗以及其內部子視窗(如果有)所產生的訊息。 - 假設一個應用程式中有一個按鈕,當使用者點選這個按鈕時,產生的
WM_LBUTTONDOWN
(滑鼠左鍵按下)和WM_COMMAND
(命令訊息)等訊息會被GetMessage
函式獲取,因為這些訊息是與應用程式自身的視窗操作相關的。
- 在大多數簡單應用程式場景下,
- 獲取系統訊息和其他視窗訊息的特殊情況
- 系統訊息:應用程式也會獲取一些系統級別的訊息。例如,當系統的顯示設定發生變化,如螢幕解析度改變時,應用程式會收到
WM_DISPLAYCHANGE
訊息,GetMessage
函式同樣會獲取這類訊息,以便應用程式能夠做出相應的調整,如重新佈局視窗內的控制元件。 - 其他視窗訊息:如果一個應用程式透過某種方式(如程序間通訊或者視窗父子關係)與其他視窗相關聯,它也可能獲取到其他視窗的訊息。例如,一個父視窗可以接收子視窗傳送的訊息,或者透過訊息鉤子(
SetWindowsHookEx
函式)攔截其他視窗的訊息,在這種情況下,GetMessage
函式獲取的訊息範圍就可能超出了應用程式自身初始建立的視窗訊息。 - 比如,應用程式設定了一個全域性的滑鼠鉤子,用於記錄所有滑鼠操作。當其他應用程式的視窗發生滑鼠點選時,透過鉤子機制,本應用程式的
GetMessage
函式也有可能獲取到相關的滑鼠訊息,從而實現對其他視窗滑鼠操作的監控。
- 系統訊息:應用程式也會獲取一些系統級別的訊息。例如,當系統的顯示設定發生變化,如螢幕解析度改變時,應用程式會收到
五、訊息的產生
- 滑鼠硬體和作業系統協作產生點選訊息
- 當使用者點選滑鼠按鈕時,首先是滑鼠硬體產生一個電訊號。滑鼠內部的電路會檢測到按鈕按下的動作,並將這個物理事件轉換為數字訊號。這個訊號透過滑鼠的連線線(如 USB 線)或者無線連線方式(如藍芽)傳輸到計算機的介面。
- 計算機的作業系統在接收到這個來自滑鼠硬體的訊號後,會對其進行處理和包裝。作業系統會根據訊號的來源(滑鼠裝置)、滑鼠的當前狀態(如位置、按鈕狀態)等資訊,生成一個對應的訊息。例如,在 Windows 作業系統中,會生成
WM_LBUTTONDOWN
(滑鼠左鍵按下)或WM_RBUTTONDOWN
(滑鼠右鍵按下)等訊息。
- 作業系統在訊息產生過程中的關鍵作用
- 作業系統負責將硬體訊號轉換為應用程式能夠理解和處理的訊息格式。這包括確定訊息的型別(如滑鼠按鍵型別、鍵盤按鍵的虛擬鍵碼等)、訊息的引數(如滑鼠點選的位置座標)。
- 作業系統還會根據視窗系統的狀態來進一步處理訊息。例如,它會判斷滑鼠指標當前所在的視窗是哪個應用程式的視窗,從而確定應該將生成的點選訊息傳送到哪個應用程式的訊息佇列。如果滑鼠指標位於多個視窗重疊的區域,作業系統會根據視窗的層次結構、可見性和焦點等因素來準確地分配訊息。
- 應用程式的被動接收角色
- 應用程式在這個過程中主要是被動接收由作業系統產生並分發的訊息。應用程式本身通常不會直接產生滑鼠點選訊息,而是等待作業系統將這些訊息傳送到自己的訊息佇列中。
- 不過,在某些特殊情況下,應用程式可能會模擬滑鼠點選訊息。例如,在自動化測試工具或者一些指令碼程式中,透過呼叫作業系統提供的相關 API(如
SendInput
函式),應用程式可以模擬使用者的滑鼠點選操作,從而產生相應的訊息併傳送到系統訊息佇列,就好像真正的使用者進行了滑鼠點選一樣。但這種情況屬於人為地透過應用程式間接產生滑鼠點選訊息,正常情況下滑鼠點選訊息的源頭還是來自於滑鼠硬體和作業系統的處理。
六、常見框架的訊息迴圈
- 基於傳統 Windows API 開發的情況
- 如果是使用傳統的 Windows API(如 Win32 API)開發包含 UI 窗體的應用程式,一般會有訊息迴圈。因為在這種情況下,為了處理使用者與 UI 窗體(如視窗、按鈕、選單等)之間的互動,需要透過訊息迴圈來獲取和處理各種訊息。
- 例如,在一個簡單的 Win32 視窗應用程式中,
WinMain
函式通常會包含一個訊息迴圈,用於從訊息佇列中獲取訊息(如使用者的滑鼠點選、鍵盤按鍵訊息),並將這些訊息分發到對應的視窗過程函式進行處理。這個訊息迴圈是保證 UI 窗體能夠正確響應使用者操作的關鍵機制。
- 使用高階框架開發的情況
- MFC(Microsoft Foundation Classes)框架
- 在 MFC 框架下開發的應用程式,當建立了 UI 窗體(如對話方塊、文件檢視結構的視窗等)時,訊息迴圈是由框架自動管理的。開發者在建立 MFC 應用程式時,不需要像在 Win32 API 中那樣顯式地編寫訊息迴圈程式碼。
- MFC 內部會在應用程式啟動時建立訊息迴圈,並且會根據應用程式的結構(如對話方塊的訊息對映、文件檢視的訊息處理機制等)將訊息正確地分發到對應的處理函式中。這個過程對於開發者來說是相對透明的,但訊息迴圈機制依然存在於幕後,用於處理與 UI 窗體相關的訊息。
- .NET Framework(Windows Forms)和.NET Core(Windows Presentation Foundation - WPF)
- 在 Windows Forms 應用程式中,當建立了一個包含 UI 窗體的應用程式時,
Application.Run
方法會啟動訊息迴圈。這個方法隱藏了訊息迴圈的複雜細節,使得開發者可以更專注於 UI 設計和事件處理。 - 類似地,在 WPF 應用程式中,也有一個類似的訊息處理機制。WPF 應用程式以事件驅動的方式執行,透過處理各種事件(如按鈕點選事件、視窗載入事件等)來響應使用者操作,其底層也是透過訊息迴圈來處理這些事件,只是在程式設計模型上更側重於事件處理,而不是直接處理訊息迴圈的程式碼。
- 在 Windows Forms 應用程式中,當建立了一個包含 UI 窗體的應用程式時,
- MFC(Microsoft Foundation Classes)框架
- 特殊情況:程序中 UI 窗體的被動顯示或簡單嵌入
- 有時候,一個程序可能會有一個 UI 窗體,但這個 UI 窗體只是簡單地被顯示或者嵌入,而沒有真正的互動需求。例如,一個程序主要用於後臺資料處理,但會彈出一個簡單的進度報告視窗,這個視窗只需要顯示進度資訊,不需要響應使用者操作。
- 在這種情況下,可能不會有完整的訊息迴圈來處理複雜的使用者互動訊息。不過,即使是這樣的簡單 UI 窗體,通常也會有一些基本的訊息處理機制,用於確保視窗能夠正確地顯示和更新(如處理
WM_PAINT
訊息來進行重繪),但這與完整的、用於處理各種使用者互動的訊息迴圈有所不同。
七、模態對話方塊和非模態對話方塊在訊息迴圈上有什麼不同
- 模態對話方塊的訊息迴圈特點
- 訊息迴圈的阻塞性質
- 模態對話方塊建立並顯示後,會啟動自己的訊息迴圈,並且這個訊息迴圈會在一定程度上阻塞其父視窗(或呼叫它的視窗)的訊息迴圈。當模態對話方塊顯示時,使用者通常只能與該對話方塊進行互動,而不能操作它後面的父視窗或其他視窗。
- 例如,在一個文字編輯應用程式中,當使用者選擇 “開啟檔案” 選單項並彈出模態的 “開啟檔案” 對話方塊時,父視窗(文字編輯視窗)的訊息迴圈好像被 “凍結” 了。使用者無法在這個模態對話方塊存在時,對文字編輯視窗進行如編輯文字、調整視窗大小等操作。
- 訊息處理範圍相對狹窄
- 模態對話方塊的訊息迴圈主要關注自身相關的訊息。它會集中處理與對話方塊內的控制元件(如按鈕、文字框等)相關的訊息,如
WM_COMMAND
訊息(用於處理按鈕點選等操作)、WM_INITDIALOG
訊息(用於對話方塊的初始化)。 - 例如,當使用者在模態對話方塊中點選 “確定” 或 “取消” 按鈕,產生的
WM_COMMAND
訊息會在模態對話方塊的訊息迴圈中被優先處理,以決定是否關閉對話方塊並返回相應的值給父視窗。
- 模態對話方塊的訊息迴圈主要關注自身相關的訊息。它會集中處理與對話方塊內的控制元件(如按鈕、文字框等)相關的訊息,如
- 與父視窗訊息迴圈的互動有限
- 模態對話方塊在關閉之前,會向父視窗返回一個值(通常是透過
EndDialog
函式),這個值可以被父視窗用於後續的決策。但在對話方塊開啟期間,除了這個返回值的傳遞機制外,父視窗和模態對話方塊之間的訊息迴圈相對獨立,父視窗基本處於等待狀態,直到模態對話方塊關閉。
- 模態對話方塊在關閉之前,會向父視窗返回一個值(通常是透過
- 訊息迴圈的阻塞性質
- 非模態對話方塊的訊息迴圈特點
- 訊息迴圈的非阻塞性質
- 非模態對話方塊顯示後,不會阻塞父視窗的訊息迴圈。父視窗和非模態對話方塊的訊息迴圈可以同時執行,使用者可以在操作非模態對話方塊的同時,繼續與父視窗進行互動。
- 例如,在圖形編輯軟體中,一個屬性設定的非模態對話方塊顯示後,使用者可以一邊在主圖形編輯視窗中進行圖形繪製操作,一邊在非模態對話方塊中修改圖形的屬性(如顏色、線條粗細等)。
- 訊息處理的獨立性和關聯性並存
- 非模態對話方塊有自己獨立的訊息迴圈來處理自身的訊息,如
WM_PAINT
訊息用於重繪自身、WM_COMMAND
訊息用於處理內部控制元件的操作。同時,它也需要和父視窗以及其他視窗進行適當的訊息互動。 - 例如,當非模態對話方塊中的某些設定發生變化(如顏色選擇改變),可能需要傳送訊息給父視窗,通知父視窗更新圖形的顯示顏色。這種訊息互動可能透過自定義訊息或者直接呼叫父視窗的函式來實現。
- 非模態對話方塊有自己獨立的訊息迴圈來處理自身的訊息,如
- 訊息迴圈的複雜性增加
- 由於非模態對話方塊和父視窗的訊息迴圈同時執行,並且需要相互配合,這使得訊息迴圈的情況更加複雜。需要考慮如何避免訊息衝突,以及如何確保訊息在不同視窗之間的正確傳遞。
- 例如,當父視窗和非模態對話方塊都有自己的定時器訊息(
WM_TIMER
)時,需要合理安排這些定時器的處理順序和時間間隔,避免相互干擾,以保證每個視窗都能按照預期處理自己的訊息,同時又不影響其他視窗的正常執行。
- 訊息迴圈的非阻塞性質