程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 系統理解Win32 API和MFC(上)

系統理解Win32 API和MFC(上)

編輯:關於VC++

Win32 API是微軟的操作系統Windows提供給開發人員的編程接口,它決定了我們開發的Windows應用程序的能力。MFC是微軟為開發人員提供的類庫,在某種意義上是對Win32 API的封裝。本文試圖從全局角度對Win32 API和MFC進行理解──給出二者的概念模型。

本文使用UML描述概念模型。Win32 API本不是面向對象的,我用面向對象的觀點去理解它,無非是想表達其全局。

本文參考了MSDN、相關書籍和網上的一些資料,在此一並感謝。

一、Win32 API的概念模型

Win32 API的object有3種:user obj,gdi obj,kernel obj。但是,如果一點不考慮OS本身的支持,就會在有些問題上疑惑,因此,我這裡把“operation system負責將中斷封裝成message”加上。

1、user obj、gdi obj、kernel obj、system 4者的關系

由於是kernel obj部分負責將另外3者聯系起來,因此我們在下圖中直接深入到kernel obj部分內部。

從圖中看到,在內存中運行的,除了“負責將中斷封裝成message”的system支持部分,還有另外3類object:kernel obj、user obj和gdi obj,每個obj都有一個句柄handle與之對應。其中,gdi obj建立了待開發的Windows 應用和外部輸出設備的聯系,kernel obj中的file建立了內存和永久存儲設備的聯系。具體說,內存中的file從可以從硬盤上來,如果這個file是可執行文件,它將生成module,module運行起來就是process,process可以包含多條thread,而thread的運行映象最終還是來自於file。thread是kernel obj中最重要的一個,因為消息隊列就是thread擁有的,只有thread才能夠接受message。對gdi obj、urser obj和file的操作,也是發生在thread中的。所以書都講,process至少擁有一個thread。

2、展開“system負責將中斷封裝成message”部分

下面展開“system負責將中斷封裝成message”部分,盡早解除對“message到底是怎麼形成的”的困惑。

3、展開“gdi obj”部分

開發人員可以通過gdi obj將app的信息反饋給User。

從圖中看到,gdi obj有8種,其中7種為:bmp,brush,pen,region,font,palette,path。另一種比較特殊的是DC,它可以被理解為一種容器,程序員通過調用SelectPallette()將pallte放入容器,通過調用BeginPath()和EndPath()將path放入容器,其它5種gdi obj,是通過調用SelectObject()放入容器的。DC又具體分為4種,其中DisplayDC就是最常用的用來支持我們“畫Window”的DC。另外,如果覺得不好理解,請參考composite設計模式。

4、展開user obj部分

4.1 第1次迭代

window在Windows應用開發中占有重要地位。

從圖中看到,window可分為3種:desktop,top-level window,child window。所有window被OS組織成tree,有專門的數據結構來管理。desktop就是樹根,desktop的子節點是top-level window,top-level window的子節點是child window,child window仍然可以有子節點,同樣歸屬於child window。tree數據結構中還記錄了4種重要信息,是4種指針:parent指針、child指針、brother指針、owner指針。這樣,從任何一個window就能很容易地找到其它window了。

好了,暫且得到 window = desktop + topLevel + child 的結論,看看全局先。畢竟,一步到位有時候並不好。

從圖中看到,window確實占有重要地位。從邏輯是講,thread是window的擁有者;但是,所有window一起決定了屏幕看起來是上面樣子,何況點擊任何一個window都會使window得相互覆蓋關系發生變化,對所用window進行統一管理是必須的,所以OS又不得不統一用window tree來管理window,反映復雜的window關系。每個window都必須有一個且只能有一個客戶區,還可能有一個title bar。再來看看CreateWindow()函數的interface spec透露了哪些信息。

從圖中看到,CreateWindow()負責為window建立與窗口類的聯系。每個window都有一個窗口類與之對應,而一個窗口類可以對應多個window。窗口類中記錄了窗口函數和菜單等資源信息,而由file生成的module正是窗口函數和資源的老家。4.2 第2次迭代

考察消息種類。

從圖中看到,每個message都是發送給某個window的。注意,msg可由SYS代碼產生,也可以由API函數產生。

進一步考察window,深入topLevel和child。

從圖中看到,OVERLAPPED風格的window是top-level window的一種,而另一種POPUP風格的window從本質上(行為上)是特殊的一種OVERLAPPED風格的window,雖然我們從coding的角度常常不這麼認為。

還是不好,因為當我們調用CreateWindow() API函數時,明明感覺CHILD、OVERLAPPED、POPUP是“window style”。我再畫一張圖。

從圖中看到,control必須是CHILD風格的,dialog必須是POPUP風格的,而一般性的window卻可以是任意風格的。

4.3 第3次迭代

總結user obj:

CreateDialog()函數示意:

從圖中看到,CreateDialog()和CreateWindow()最大的區別就是,它有對話框模板支持方便地定制dialog界面。注意,Dialog是特殊的window,窗口類它一定也是有的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved