我記得剛開始學圖形界面程式設計的時候,接觸的最早的一個函數應該就是MessageBox,之前都一直是控制台程式,突然能運作蹦出一個對話框感覺還是很新鮮的。當時還利用MessageBox寫一些惡搞程式,利用上面的yes or no 按鈕進行判斷等等。但是說實話感覺用處不是特别大,調試的時候可能會用到,是以也就沒有深入的研究和學習這個函數。後來轉到MFC了,不知怎的吧,就用起了AfxMessageBox,也是沒覺得什麼,是以也就沒多想什麼,直到今天,項目中碰到了個問題,才導緻我不得不研究一下MessageBox和AfxMessageBox兩者的異同點。
那麼我遇到的問題是什麼呢?我在主對話框中有一個按鈕,點選之後能彈出一個非模态的對話框,那麼可能在子對話框中就有一些相應的操作要進行,剛開始并沒有發覺哪裡不妥。大家知道,彈出非模态的對話框,它并不阻塞父視窗,但是焦點卻是在子對話框上,也就是當兩者有層疊關系時,你點選父視窗的邊框,父視窗并不會像我們預期的那樣跳到最上面,卻仍然是子對話框在最上面。這就比較不爽了,于是我參照了一個前輩的方法,具體見:
實作仿QQ主界面置頂(非模态對話框的顯示問題)
如文中所示的方法後,我發現确實不同了,子對話框和父對話框重疊的時候,具有焦點的那個會被放到最上面。此時,我便遇到今天我要說的問題了。我項目中遇到提示資訊需要使用者注意的基本都是Afxmessagebox來實行。那麼當我在子對話框中進行一些操作,彈出提示資訊後,我們預期的是這個小的對話框應該出現在子對話框上面,但是讓我意想不到的是,它出現在了父對話框的上面,也就是說,此時,父對話框跑到了子對話框之上,而這個彈出的對話框又在其之上。我馬上就明白,這絕對是因為視窗句柄的關系,因為我項目中寫的基本是AfxMessageBox(“xxxxxxx”,MB_OK)之類的,是以應該再加個句柄就行了,但是加進去不對了,提示調用參數太多了,這才又去檢視了萬能的百度,這才成為我想寫這篇部落格的動因。
那麼Afx是什麼呢?afx其實是微軟的一個小組名稱,Application Framework技術團隊,名為AFX小組,用以開發C++對象導向工具給Windows應用程式開發人員使用,x并沒有含義。Afx架構函數實作都是調用API函數的,你可以在VC中找到任意一個架構函數比如AfxMessageBox,單擊右鍵選轉到定義就可以看到它的源碼了,它的函數體裡面還是要調用MessageBox的。那麼此處我就明白了,Afxmessagebox是微軟對win32API函數messagebox的一個封裝,專門用在MFC中.既然說到這了,雖然一直聽說過win32 api 和mfc,但兩者到底有什麼關系呢?
Win32通常是指sdk程式設計方法,app沒有被封裝,開發人員需要自己搭程式架構;mfC則是以C++類的形式封裝了Windows的API,并且包含一個應用程式架構,以減少應用程式開發人員的工作量。更多更細緻的差別見部落格:
mfc與win32差別
這裡我就把它摘抄過來了:MFC就是 微軟給你包裝了的庫,提供了很多擴充功能,以及進階功能,這樣友善你使用,而不是自己從頭調用API來實作,而API由于是MFC下一層,自然實作更靈活,可以根據你的需要來使用,不會被MFC類庫所限制。win32和mfc程式設計的最大不同是win32是程式設計者自己把消息和響應函數聯系在一起。mfc是程式設計者采用微軟為我們做好了Messagemap機制,來處理消息。
mfc是便利的,為什麼有人不用呢?不用mfc的人群往往是從DOS時代開始從事視窗程式設計的人,他們早在mfc出世之前就編得一手好程式。長期的程式設計過程中,每人,每個TEAM都擁有了自己的消息處理機制程式庫或類庫。當然有很多人認為他的類庫比mfc使用友善。他開始為視窗程式設計的時候,mfc的TEAM的很多人還在學校裡讀書呢。如果不是從那個年代過來的人,還是用mfc吧!mfc是封裝的類,最後還是會調用win32api win32api開發效率是底一些,但比較自由.
有時候mfc是封裝的類不能滿足我們的要求,這時就需要我們自己用api來開發啦 MFC是專注于使用者界面的,而Windows SDK專注于UI, console,Windows服務,嵌入式,驅動多種類型的程式, MFC是一套類庫,适應範圍窄,可以搞ERP軟體,但效率不如其他語言高,而且類庫并沒有對DDK,openGL,D3D等專項上司的函數庫進行封裝。而Windows SDK提供了專題開發的平台。
MFC中對所有的句柄,對象,消息都進行了嚴格的檢測,如果你不知道它的内部機制,随便調用函數很容易出錯,而SDK提供的是一種寬松的開發環境,你可以用面向對象的思想定義自己的類,對界面控件進行封裝。
在一些專題開發項目,你可以不懂MFC,但是在一些正常的軟體開發,你必須熟悉MFC,同時還要懂SDK. win32是windows下的最基本的程式設計方式,使用它得到的代碼最幹淨最有效率,也是最底層,它是其它所有方式實作的基礎。一般指隻使用API和SDK。
MFC是對win32的封裝,使用win32程式設計方法,寫了一個又一個類,讓我們不用再重複大量勞動。但畢竟是封裝,是以不可能完全實作win32所有功能。用着雖然友善,但距離細節畢竟遠了,在個性個、特殊化方面還有差距。 兩者相比,win32更本質,MFC更抽像。
可能說的有點遠,但其實沒有,MessageBox是win32API函數,而AfxMessageBox是mfc裡封裝之後的函數。那麼究竟兩者有什麼異同呢?
對于AfxMessageBox,定義如下:(來自百度百科)
int AfxMessageBox( LPCTSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0 );
int AFXAPI AfxMessageBox( UINT nIDPrompt, UINT nType = MB_OK, UINT nIDHelp = (UINT) –1 );
在第一種形式中,lpszText表示在消息框内部顯示的文本,消息框的标題為應用程式的可執行檔案名(如Hello)。在第二種形式中,nIDPrompt為要顯示的文本字元串在字元串表中的ID。函數調用時會自動從字元串表中載入字元串并顯示在消息框中。nType為消息框中顯示的按鈕風格和圖示風格的組合,可以采用|(或)操作符組合各種風格。
按鈕風格
MB_ABORTRETRYIGNORE 消息框中顯示Abort、Retry、Ignore按鈕
MB_OK 顯示OK按鈕
MB_OKCANCEL 顯示OK、Cancel按鈕
MB_RETRYCANCEL 顯示Retry、Cancel按鈕
MB_YESNO 顯示Yes、No按鈕
MB_YESNOCANCEL 顯示Yes、No、Cancel按鈕
圖示風格
MB_ICONINFORMATION 顯示一個i圖示,表示提示
MB_ICONEXCLAMATION 顯示一個驚歎号,表示警告
MB_ICONSTOP 顯示手形圖示,表示警告或嚴重錯誤
MB_ICONQUESTION 顯示問号圖示,表示疑問
使用時,可以隻調用AfxMessageBox(LPCTSTR lpszText);這樣預設風格為AfxMessageBox(LPCTSTR lpszText,MB_OK|MB_ICONEXCLAMATION );
2傳回值
編輯
傳回值有8種,如果記憶體不夠,則傳回0,否則傳回以下值中的一種,分别對應相應的按鈕被點選:
IDABORT、IDCANCEL、IDIGNORE、IDNO、IDOK 、IDRETRY、IDYES。
MessageBox的定義如下:
MessageBox顯示一個模态對話框,其中包含一個系統圖示、 一組按鈕和一個簡短的特定于應用程式消息,如狀态或錯誤的資訊。消息框中傳回一個整數值,該值訓示使用者單擊了哪個按鈕。
int WINAPI MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
hWnd:
消息框的擁有窗此參數口。如果為NULL,則消息框沒有擁有視窗。
lpText:
消息框的内容。如果使用了Unicode庫,則把文本變成:
1TEXT(/sometext/)
lpCaption:
消息框的标題。如果使用了Unicode庫,則把文本變成:
TEXT(/sometext/)
uType:
指定一個決定對話框的内容和行為的位标志集。此參數可以為下列标志組中标志的組合。指定下列标志中的一個來顯示消息框中的按鈕以及圖示。
當然此處就可以明顯的看到兩者最大的不同在于messagebox第一個參數hWnd,AfxMessageBox是全局函數,在任何地方都能用,但MessageBox就不能如此用了,因為第一個參數的限制,它隻能用在CWnd類和其派生類當中。那麼至此,我覺得我的問題應該找到了,并能夠解決了。想要在mfc裡調用具有視窗句柄的messagebox,則應該這樣
::MessageBox((GetSafeHwnd(),”text”,”title”,MB_OK)
其中GetSafeHwnd()函數擷取目前對話框的視窗句柄。
那麼在運作之後,點選彈出子對話框,再彈出提示消息,此時便和我們預想的效果是一樣的了,提示的消息出現在子對話框之上,焦點任然是子對話框。
OK,至此,完成,我今晚的部落格!加油!
拙見,小記!