Visual C 模態對話方塊訊息處理機制的分析

2021-04-01 18:23:22 字數 3160 閱讀 6806

摘要:訊息驅動機制是windows作業系統的根本,模態對話方塊訊息處理又是不同於一般訊息處理的特殊形式。通過分析這種訊息機制的原理,可用來處理類似的程式設計要求。

在windows作業系統中,面向使用者的gui基本上可分為對話方塊形式和文件/檢視兩種表現形式。對話方塊的顯示方式又可分為模態對話方塊和非模態對話方塊,以適應不同的使用者互動需求。由於對話方塊和文件/檢視框架結構各有特色,能不能將文件/檢視框架結構當作一對話方塊來使用,或在對話方塊中實現文件/檢視框架結構內的特色功能呢,答案是肯定的。

下面,從windows 作業系統訊息驅動機制開始,進而**模態對話方塊實現過程的訊息封裝、傳遞和處理機制,最後以模態的形式顯示應用到文件/檢視框架結構中的例項作為對所講內容的驗證和實踐。

一、windows訊息機制

windows是一種物件導向的體系結構,windows環境和應用程式都是通過訊息來互動的。windows應用程式開始執行後,windows為該程式建立乙個"訊息佇列(message queue)",用以存放郵寄給該程式可能建立的各種不同視窗的訊息。訊息佇列中訊息的結構(msg)為:

typedef struct tagmsgmsg;

其中第乙個成員變數是用來標識接收訊息的視窗控制代碼;第二個引數便是訊息標識號,如wm_paint;第三個和第四個引數的具體意義同message值有關,均為訊息引數。前四個引數是非常重要和經常用到的,至於後兩個引數則分別表示郵寄訊息的時間和游標位置(螢幕座標)。把訊息傳送到應用程式有兩種方法:一種是由系統將訊息"郵寄(post)"到應用程式的"訊息佇列"這是"進隊訊息"win32 api有對應的函式: postmessage(),此函式不等待該訊息處理完就返回;而另一種則是由系統在直接呼叫視窗函式時將訊息"傳送(send)"給應用程式的視窗函式,屬於"不進隊訊息"對應的函式是sendmessage()其必須等待該訊息處理完後方可返回。

對於每乙個正在執行的windows應用程式,系統為其建立乙個"訊息佇列",即應用程式佇列,用來存放該程式可能建立的各種視窗的訊息。應用程式中含有一段稱作"訊息迴圈"的**,用來從訊息佇列中檢索這些訊息並把它們分發到相應的視窗函式中。

訊息迴圈**是應用程式中主函式winmain ( )中類似如下的程式段:

while(getmessage(&&msg,null,null,null))

由此可見,所謂"訊息迴圈",實際是程式迴圈。

windows 應用程式建立的每個視窗都在系統核心註冊乙個相應的視窗函式,視窗函式程式**形式上是乙個巨大的switch 語句,用以處理由訊息迴圈傳送到該視窗的訊息,視窗函式由windows 採用訊息驅動的形式直接呼叫,而不是由應用程式顯示呼叫的,視窗函式處理完訊息後又將控制權返回給windows。

二、模態對話方塊的訊息處理

由上面我們看到,windows是乙個巨大的訊息驅動結構,由使用者發出訊息,系統響應處理。非模態對話方塊是響應乙個訊息,系統處理乙個訊息,處理完畢後返回控制權給windows。文件/檢視框架結構與其類似。模態對話方塊在對話方塊建立後,掛起外部的訊息,只是響應對話方塊內部的訊息,而外部訊息則全部"過濾"掉了,直到系統接收到wm_destroy或wm_close後,系統返回控制權給模態對話方塊建立前的執行緒,繼續模態對話方塊建立前的執行緒將執行下面的**。

讓我們看看下面的對話方塊domodal實現**:

try}

}catch_all(e)

end_catch_all

file://enable 父視窗

if (benableparent)

::enablewindow(hwndparent, true);

if (hwndparent != null && ::getactivewindow() == m_hwnd)

::setactivewindow(hwndparent);

// 刪除對話方塊

destroywindow();

postmodal();

… …}

可以看到,在此實現**中,並沒有開闢新的執行緒。系統是在runmodalloop()中進行訊息迴圈。當 m_nflags 為 wf_continuemodal時,系統繼續模式狀態。runmodalloop()函式實際上也是一for(;;)迴圈,控制重新分派windows訊息。直到continuemodal()返回false,而當呼叫endmodalloop()時,continuemodal()返回false。此時,標誌著模態顯示的結束。因此,實現模態對話方塊訊息處理的核心部分為runmodalloop()和endmodalloop()函式。

三、以模態的形式顯示應用到文件/檢視框架結構例項

(2)第二步選取single document(單文件)。

(3)其餘幾步均為預設值。

(4)用classwizard新增一新類csubmodeframe,以cframewnd為基類。

(5)新增csubmodeframe的實現函式domode();

int csubmodeframe::domodal()

centerwindow();

trycatch_all(e)

end_catch_all

if (benableparent)

::enablewindow(hwndparent, true);

if (hwndparent != null && ::getactivewindow() == m_hwnd)

::setactivewindow(hwndparent);

// destroy modal window

destroywindow();

return m_nmodalresult;

} (6)新增csubmodeframe的實現函式endmode()

void csubframe::endmodal()

}(7)新增cmodeframeview的實現函式onlbuttondblclk()

在此函式的訊息處理中:可以象顯示對話方塊一樣處理csubmodeframe類。

csubmodeframe submodeframe;

if(submodeframe.domode())

(8)編譯執行工程,雙擊檢視,就會彈出模態的子文件/檢視框架結構

結論:通過上面的分析和例項可以看出,深入研究了解windows的訊息處理機制,可利用訊息對windows的事件進行任意的定製和處理,不用拘泥於系統原有的模式。對進行深入windows程式設計是很有必要的。

Windows SDK 非模態對話方塊的訊息處理

在sdk中使用非模態對話方塊時,主迴圈中必須插入下列 1.while getmessage msg,null,0,0 6.我的問題是 為什麼要呼叫isdialogmessage?非模態對話方塊與主視窗有什麼區別?如果不呼叫isdialogmessage,訊息能不能傳遞到對話方塊?如果一定要呼叫isd...

模態對話方塊 非模態對話方塊 標準對話方塊 檔案對話方塊

模態對話方塊 qdialog 非模態對話方塊 qdialog 標準對話方塊 關於對話方塊 問題對話方塊等 qmessagebox 檔案對話方塊 qfiledialog 標準對話方塊還有 qcolordialog 選擇顏色 qfiledialog 選擇檔案或者目錄 qfontdialog 選擇字型 q...

模態對話方塊與非模態對話方塊

1.對話方塊分類 按工作方式不同,可將對話方塊分成兩類 模態對話方塊 modal 在關閉模態對話方塊之前,程式不能進行其他工作 如一般的 開啟檔案 對話方塊 非模態對話方塊 modeless 非模態對話方塊開啟後,程式仍然能夠進行其他工作 如一般的 查詢與替換 對話方塊 2.對話方塊建立 模態對話方...