自從3月2日下午4:20又幾分鐘收到這本經典巨作《window程式設計》我就很興奮,這本書給我的感覺就想《C++Primer Plus》,或者更好,因為它們兩者都兼備了一個共同特點:讓你消除基礎盲點,解除你從前的疑惑,一切都那麼有始有終。
都過了10天了,現在才看到第十章,哎,是有點慢,但是因為沒有一味看書,而是基本上把書上所有出現過的程式,以自己了解并獨立寫出的方式進行着。自己感覺還可以,覺得消除了以前很多覺得很神秘,很難懂的,例如:GetSystemMetrics(雖然現在覺得是那麼基本的函數,但以前看到這個函數感覺就是這個函數跟系統牽連很大,很怕!),函數視窗視口,映射模式自由變換,還有子視窗建立等等,好多東西。這也驗證了這本聖經的不朽,讓你學完這後感覺知識體系好清楚。雖然内容多,但是不太亂。說不太亂隻要是因為windows本身的原因,而不是這本書講述的原因,都知道windows的函數以及消息定義,消息通知這類,如果全看能讓你看個幾個月的。
鋪墊了這麼多該進入這篇部落格的主題了,那就是自我總結關鍵要點。
我以章節順序一一總結自己認為的重點:
第一章:起步
windows簡史。1981年pc機才開始出現,那個時候風靡的作業系統霸主就是MS-DOS。而後1983年微軟宣布windows。(而在此之前蘋果公司發行過Lisa,提出與字元界面不同的思路。蘋果1984年釋出了Macintosh成為了圖形界面的标準。)1985年釋出了window1.0。1987年釋出了window2.0,同期與IBM公司推出了OS/2作業系統。1990年推出了window3.0,同時與IBM公司分道揚镳,微軟不再參與os/2,而專心自己的Windows。1992年window3.1釋出,1993年windowNT釋出。緊接着就是我們熟悉的window95,window98。而到現在的windows
2000,windows2002,xp,vista,window7等等。
動态連結庫的作用。原來我們使用的API全都是以動态連結庫的形式連接配接到我們程式裡面的,怨不得程式Debug調試下,輸出框裡面N多已加載xxx.dll。而我們用的C語言的函數,例如什麼strlen(),都是相當于把代碼加到你程式裡面,程式本身會變大。而導入庫的作用就是為了加載dll做好準備資訊用的,這是由于導入庫本身的覺得,因為它就是記載這相應dll位址,以及dll裡面的位址,程式隻有在連接配接階段通過lib才能把這些資訊加到程式裡面,然後程式實際運作的時候就根本不需要lib了,因為資訊已經被加載到了程式中。這就可以解釋為什麼以前的時候我們編寫Ogre,語音引擎需要dll,還需要lib,還需要頭檔案(頭檔案是一種友善調用dll函數的方法,在dll裡面有詳細講解,這種通過頭檔案方式調用dll函數成為“隐式連接配接”)。
我們經常看到的LP,其實是以前window16版本遺留下來的東西,那時候采用段位址尋址,實體位址包括段位址和段内位址。長指針可以用于不同段的尋址,而NP,也就是近指針可以用于同一段位址的段内尋址。不過32位的windows作業系統早就不分這個,LP,NP都是一樣的,隻是為了相容以前版本的程式。你會經常看到這樣的系統定義:struct POINT {}* PPOINT,*LPPOINT,*NPPOINT;這就可以證明LP,NP,P都是一樣的。
命名方式:匈牙利命名法。也就是所有變量的第一個或者前幾表示類型的字元要小些,以後每個單詞或者其簡寫的第一個字元大寫。例如:int iLen;HWND hwnd;HWND hwndDlg;還有一些具有特殊意義的非類型小寫,如:int cbWndExtra;其中的cb,c是count的縮寫就是數量,個數的意思,b是byte的縮寫是位元組的意思,那麼cbWndExtra就是為視窗預留的位元組數,這麼一個變量。這個變量的意義這裡不用追究以後自然會知道。
MessageBox原來有很多形式。有隻有一個“确定”按鈕的,有“确定”和“取消”兩個按鈕的,有“忽略”,“重試”,“取消”三個按鈕的,還有什麼四個按鈕的。還可以指定消息框出現的圖示。有資訊提示的,有錯誤的,有詢問的。
第一張說的還真不少!無語了,看來這本書就是這樣,讓你知道很多,就連總結也很多。看下一章。
第二章:Unicode簡介
基本上就是一點UNICODE的來曆。原來的時候美國字元少,自己夠用,後來考慮歐洲就得擴充字元,再後來再往東擴充,電腦用到了亞洲,終于美國人傻眼了,這麼多字元了,開始想方設法,第一個方法是雙位元組字元集(DBCS)。但是這個字元集很怪,有些字元時一個位元組,有些字元時兩個位元組。這就使得程式設計麻煩,因為要确定指針的位置(處于第一個字元),不能簡單的和首字元位址相減得到偏移量,因為有些字元時一個位元組的。而後就出現了UNICODE字元集,對了确實是唯一的,因為它統統用兩個位元組表示一個字元,是以不會有任何歧義了。但是浪費空間。(而後就出現utf-8,utf-16,utf-32等UNICODE解決方案,window裡面用utf-16)。還要明确一個概念就是“寬字元”是一種訓示用多個位元組表示一個字元的方法,是以UNICODE是一種寬字元。而不能用寬字元就是UNICODE。
因為字元所用的位元組不同,是以所有牽扯到字元的函數都需要新增一個寬字元版本,這就是我們經常看到的什麼strlen,對應wcslen(這是個c函數,windows裡面有不同的宏定義,以友善實作不同編碼的編譯)。以後所有的常量字元串統統加上TEXT(""),這樣可以用unicode編碼方案編譯,也可以用ASCII編碼方案。
接觸了個sprintf,fprintf,分别是将格式化到字元串,格式化到檔案。還有vsprintf用于輔助實作不定量變量輸出的函數。基本不用。c語言也是用了宏定義,window也是用了宏定義,就是為了讓程式能夠在unicode和ASCII下是用相同函數名,而不用關心是否是寬字元版本什麼。因為編譯器幫你決定。
看來第二章稍微少點。嘿嘿。明天寫下一張吧。
今天是3月13日繼續總結。
第三章:視窗與消息
這裡呢,現在回想一下是那麼的基礎,但是第一次見到視窗建立的整個過程還是很驚心動魄,很讓人害怕,你要知道,對于初學者使用一個10個參數WNDCLASS結構體,和使用11個參數的CreateWindow真的很吓人得。但好在這些都過去了。
WNDCLASS裡面需要注意的基本上沒事了,就是系統資源的使用,如GetStockObject,LoadIcon(NULL,IDI_APPLICATION);LoadCursor(NULL,IDC_ARROW);特别是IDI_APPLICATION,IDC_ARROW是MAKEINTRESOURCE的宏定義,以實作将數字ID轉換成字元串指針,但本質不用這個字元串指針做事情,而是如果字元指針的高位是0的話,LoadIcon等這些函數就知道第16位是資源ID。
CreateWindow第一個參數是視窗類名稱,而不是視窗類對象。說到視窗類,可能就要說為什麼要将這個視窗建立弄成兩部分,我認為有兩方面原因:1,首先是為了視窗類的多次使用,也就是說很多視窗的一些視窗類變量的值是一樣,而且事實也是這樣,是以把視窗類單獨出來,可以為以後視窗建立提供友善。2,本身兩者是各司其職,視窗類主要是一些屬性上的東西,和視窗本身有關聯,但是還是不是視窗本身,而CreateWindow就是完全側重視窗本身的外觀的東西和本身屬性的東西。而且CreateWindow函數本身會發送WM_CREATE消息,說是發送消息感覺像異步,實際上是同步,是在CreateWindow函數裡面回調了WndProc,調用完了才回去繼續完成CreateWindow。是以記住所有的發送消息的字眼就是同步函數調用。而如果說投遞消息的話,那就是發到消息隊列,就有異步的意思了。
另外CreateWindow裡面一個重要點就是,如果作為子視窗建立的話,hMenu這個參數就作為子視窗ID,這是規定。
CreateWindow完了就是ShowWindow了,就是因為各司其職,CreateWindow建立記憶體中的視窗基本資料,而ShowWindow是将抽象的視窗顯示到螢幕。這個函數發送WM_SIZE消息,我說發送,你懂得,同步回調視窗過程。
UpdateWindow發送WM_PAINT的,你懂的。但是需要注意的是,WM_PAINT消息是根據無效區域進行重畫的。為什麼是根據無效區域進行重畫的呢,就是因為BeginPaint傳回的HDC決定的,因為這個hdc裁剪了那無效區域,所謂裁剪就是隻重畫裁剪了的區域,不在此區域的不予重畫。是以如果你沒有無效區域,你發送UpdateWindow是無用的。而且WM_PAINT還有很多需要注意的地方,等在WM_PANT消息那總結吧。
視窗過程,我們把我們關心的消息用case語句攔截一下,但是我們因該知道我們攔截的消息是否有系統預設處理,如果有預設處理的話,在case塊處理完了break出來,如果知道系統沒有預設處理的話,那麼就直接return就可以了。
WM_PAINT消息,應該注意的事這個語句裡面一定要寫BeginPaint消息,記得自己有以下寫WM_TIMER消息,在WM_CREATE消息裡面SetTimer了,但是一直收不到WM_TIMER消息,原來是WM_PAINT沒寫代碼,但想先看WM_TIMER效果,但是因為WM_PAINT裡面沒有BeginPaint,而BeginPaint是清除無效區域的。可能說了你也不明白,關鍵是WM_PAINT在消息隊列裡面是怎麼被清除的呢?不要以為你處理的WM_PAINT就沒了,錯了,是清除無效區域是,就會清除消息隊列裡面的所有WM_PAINT消息。繼續說剛才的bug,因為WM_PAINT沒有BeginPaint,是以WM_PAINT就一直清除不了,就會一直重複的WM_PAINT處理過程,是以WM_TIMER消息就沒有機會處理了,因為WM_TIMER也是隊列消息。隊列消息就是要經過消息隊列的消息。每個程式有一個消息隊列。經過消息隊列的消息可以說是序列消息了,就是遵守“先來後到”和“優先級”。
GetMessage函數呢,是從消息隊列裡面取消息。如果有,就取出來,然後交給TranslateMessage,如果是鍵盤消息,TranslateMessage就判斷這個鍵盤消息是否産生字元消息,如果産生字元消息,TranslateMessage就往消息隊列裡面添加字元消息,作用僅此而已(目前為止)。DispatchMessage是将消息派送到相應的視窗過程。
對了WinMain函數裡面的hInstancePrev永遠是0,為什麼要用這個東西,就是因為以前的程式用,是以為了相容性就保留了,而且永遠置為0,這樣也會讓原來的程式邏輯正确。啊,我們居然知道一點相容性的東西了,以前的時候總是聽到書上或者别人說什麼windows相容性很強,自己總無法了解什麼叫相容性。啊,我們也可以懂一點點相容性了。呵呵。
啊,說是總結,卻還是寫了很多。不過和書上的比起來,已經很少了,不知道又打了多少錯别字。嘿嘿。
今天是3月21日,已經過了8天都沒寫了,因為上個星期看到很多新東西,而起有些程式比較大,有點累就沒寫,還好好休息了休息,今天繼續努力咯!
第四章:文本輸出
幾種情況下會出現WM_PAINT消息。視窗尺寸變化(這要求視窗的類型CS_HREDRAW,CS_VREDRAW),視窗被遮擋,用InvalidateRect指明無效矩形,一些windows函數如ScrollWindow,ScrollDC使得視窗畫面滾動,而導緻一些無效區域産生。其他的就不用太在意了。有些windows會儲存,有些不會。總之不用太在意,一般不影響你程式。
上面說到無效矩形,就是用InvalidateRect函數指定的矩形就是無效矩形,這個函數會發出WM_PAINT消息,用BeginPaint函數得到的視窗句柄隻會在無效矩形上面重新繪畫(當然是繪畫在無效矩形裡面的圖形了)。或者通過GetUpdateRect來得到無效矩形或者稱為“更新矩形”。
這一章是第一章與圖形相關的章節,說到GDI,就不得不說一個令所有初次接觸GDI的新手感到困惑和恐懼的單詞了。那就是Device Context。這個到底是什麼,什麼叫做裝置上下文呢?上下文經常出現在國文課本裡面,但是裝置怎麼跟語扯上邊了呢?這可能就是計算機的無所不涉及吧。我了解是這樣的:首先我要說什麼是裝置,這裡說的裝置比較抽象一點,不要一味的去想顯示器裝置,确實和它有關系,但用另一種觀點去看能夠有利于我們程式設計的了解。直接給裝置的比較完整的描述比較苦澀。還是這樣說吧!可以這麼說,如果你知道什麼是客戶區的話,你就可以更好了解裝置。因為我們一般繪畫都在客戶區,雖然也可以在整個視窗繪畫,但是不是正規做法。為什麼我們可以單獨在客戶區繪畫,而且繪畫就好像是在一個獨立的裝置上繪畫,我提到了裝置,這是因為我們在客戶區繪畫時,如果坐标出了客戶區就不會顯示出來。如果我們坐标出了客戶區而影響到其他視窗的話,我想誰都不願意。你看客戶區這個時候就好像一個單獨的顯示屏,具有完整的繪畫體系。是以我們可以成客戶區是一個裝置。同樣視窗也是裝置。螢幕也是裝置。是不是感覺這些裝置有很多重疊區域,感覺不像。但是如果你得到這些裝置環境的句柄,在上面繪畫就相當于在一個獨立的裝置繪畫。剛才說到裝置環境句柄,那麼我們說一下裝置環境吧,裝置你有點認識了,那裝置環境是什麼呢?我問你你想在客戶區寫字是不是直接用TextOut将你想寫的字寫出來就可以了!是的,但是我要問你,你寫的字的字型是什麼顔色的,字型什麼類型的。如果你用直接畫線的話,線條是虛線還是實線。這些你都不用再使用前設定,裝置有預設設定。而我認為這就是裝置的環境,就是裝置目前的一種狀态。那麼裝置環境句柄呢?句柄就是一個值,通過它我們可以引用到我們想要的對象,而windows核心對象都是通過句柄來因為。暫時不要管什麼是核心對象,簡單的認識就是很重要的windows對象。那麼裝置環境句柄就可以讓我們得到裝置環境的很多資訊。寫的真夠多的。
列舉幾種得到裝置環境句柄的方法:BeginPaint專用于WM_PAINT消息,因為它就是為WM_PAINT量身定做的。裡面包含了很多重畫的重要資訊,比如說無效矩形。GetDC是得到各種裝置句柄,但不包含任何重畫資訊。CreateDC是建立像螢幕裝置環境句柄,列印機句柄等。CreateIC是得到用于擷取資訊而不能繪畫的句柄。
文本輸出的話,就我看來基本上在顯示方面可以分為兩個函數,一個經典的TextOut函數,另一個是格式輸出的函數DrawText。但要是輸出比較工整的話,那麼要得到一些具體的字型資訊,比如你要使用什麼字型在客戶區進行輸出,這些字型的高度和寬度直接影響你的輸出效果,是以一般的字型輸出的話,都會在WM_CREATE消息裡面得到你欲使用字型的資訊。然後以後就可以用了,不過預先說明,我們這裡能處理的是等寬字型,也就是SYSTEM_FIXED_FONT,或者在用LOGFONT的時候制定pitch的時候制定FIXED_PITCH,那樣也能得到等寬字型。因為非等寬字型的處理确實比較麻煩,在排版和布局上要做很多細緻活。
在說到字型時,就應該知道計算機對字型處理的一些基本資訊,這些基本資訊可以用過GetTextMetrics函數得到,将結果儲存在TEXTMETRIC類型的變量裡面。其中有tmHeight,tmAveCharWidth,tmExternalLeading,tmInternalLeading,tmAscent,tmDescent。tmAscent從字型基準線到字型能達到的最高處(包括普通字元上面的一些音調符号),而tmDescent是基準線到所有字型能達到的最低處。基準線就想我們在信紙上寫g一樣,我們會把g的彎鈎下載下傳橫線下方,把g的o解除安裝橫線上方,而橫線就是我剛才說的基準線。tmInternalLeading就是普通字元上面的音調符号(如果有的話)。tmExternalLeading是不屬于字型,它是行間距。基本上可以這麼認為,當然有更美觀的排版在tmExternalLeading的基礎上進行修正,已達到視覺最好的效果。tmAveCharWidth是平均字元寬度,為什麼說平均,那是對非等寬字型而言的,等寬字型的話就是每個字元的寬度。tmHeight就是tmAscent和tmDescent的和。而對我們最重要的就是tmHeight,tmExternalLeading,tmAveCharWidth。因為tmHeight+tmExternalLeading就是一行字型所占的所有高度。tmAveCharWidth就是字型的寬度了。
用到字型的話我們就要說一下很重的細節了。字型,筆,畫刷都會牽扯到背景顔色和背景模式,不要把這個和視窗背景混了。視窗背景是進行無效區域重新整理用。而字型的背景顔色和背景模式是在指定位置輸出字型時,将字型寫在背景顔色上,在經背景模式變換,再“貼”到你要顯示的地方。當然背景顔色和背景模式在預設模式下和系統的其他預設設定是很和諧。可以通過SetBkColor和SetBkMode來改變。具體函數用法可以自己查。
滾動條基本上就是基本上就用SetScrollInfo了,像如SetScrollRange,SetScrollPos基本都可以被SetScrollInfo代替。而且SetScrollInfo提供更多便利,比如滾動最後一頁的設定,不應該把檔案的最後一行放到最後一頁頂部,而應該最後一頁底部。而放到底部需要自己計算,而SetScrollInfo幫你計算。
滾動條中經常使用ScrollWindow,因為效率很高,不會出現螢幕很卡的現象。但是ScrollWindow是為數不多的不用裝置句柄的函數。是以因該是它不屬于GDI子產品。在滾動條中應該判斷滾動條是否到頂了,或者到底了,以避免不必要的重畫。
哇,好累啊,哎,寫書的人你們辛苦了!寫完後沒怎麼檢查,誰給核稿啊?
今天3月23日,第五章要開始了,要知道這是多麼重要,多麼對像我們這樣的菜鳥給力的一張。不過内容真的好多又重要!
第五章:繪圖基礎
首先來說的話,我們應該知道windows通過GDI子產品,使得我們的繪圖完全獨立于硬體。使得繪圖操作可以被移植,當然盡量是圖像輸出類型一樣的裝置,因為矢量裝置不能使用很多光栅操作,而使得光栅操作的函數不能用到矢量裝置上。
我們需要經常用到的,用于得到系統資訊的函數應該知道:GetSystemMetrics,GetDeviceCaps,GetTextMetrics;
對于圖像的一些基本屬于應該清楚:分辨率有的時候是指裝置總長度(寬或高)所用的像素數。而本書的作者則更傾向于用每度量機關下的像素數為分辨率,而用像素規模表示裝置總長度得像素數。用度量尺寸或規模來表示裝置總長度的實體大小。還有HORZSIZE和HORZRES不同,一個是度量機關,一個是像素機關。且前者從系統得到的不一定對。作者不建議用實體尺寸去幹一些事。
如果我們在某次操作中,要改變我們裝置環境做一些,但接着又要在回到原來狀态,那麼SaveDC,RestoreDC是必不可少,且經常用堆棧形式。SaveDC(hdc);RestoreDC(hdc,-1);-1表示回到上一次狀态。
各種函數打統計:點:SetPixel,GetPixel。線:MoveToEx,LineTo,Polyline,PolylineTo,PolyPolyLine,Arc,PolyBezier,PolyBezierTo。填充類型:Rectangle,Ellipse,Chord,Pie,Polygon,PolyPolygon(畫多邊形用處極大)
畫筆,畫刷各種樣式都應該了解。這些對象也前者到背景顔色和背景模式。
另外很重要的ROP操作,也就是Raster operation。光栅操作。通過SetROP2,2代表兩元,就是兩個對象間的關系,如畫筆顔色和目标顔色。通過使用巧妙的SetROP2,可以極大提高我們程式的繪圖效率,而不用設定什麼無效區域,那樣很可能要重畫背景。是以ROP應該好好看看!
要知道一點基本知識,其實我們背景重畫就是用目前畫刷(8*8的位圖),不斷重複粘貼,完成的。而這個目前畫刷不是通過SelectObject就可以更換,那是你的視窗類中的資料,要修改用SetClassLong。說到SetClassLong,就要知道其他三個超強函數,GetClassLong,SetWindowLong,GetWindowLong。
映射模式,這可是非常非常重要的。被我認為是繪畫中的靈魂。因為如果你不懂映射,或者沒搞清楚,那麼那些建立在映射上的友善操作你是很難了解的。有一種裝置坐标映射WM_TEXT,其他的已經規定了的都是度量映射,也就是牽扯到實體機關。這是為了友善我們建立裝置無關的一些資訊用的。比如你要建立30mm寬,30mm高的,你不用去計算30mm高在你電腦上有多少像素,你隻需要換成WM_LOMETRIC即可或者其他的。度量映射下的y正方向和裝置坐标映射下的y正方向正好相反。但是最好用的還屬WM_ISOTROPIC和WM_ANISOTROPIC,這讓我們的映射坐标無比靈活。你可以自己制定1代表多少像素,或者你覺得對你程式好用的機關,如一個字元高度。WM_ISOTROPIC是各向同性,WM_ANISOTROPIC是各向異性。但WM_ANSIOTROPIC并不是必須是寬,高機關必須不同的,隻是說明它可以勝任寬,高不同機關的情況。WM_ISOTROPIC讓你的寬和高的機關一定是一樣,即使你用不同的寬高數值,因為windows會檢查你的數值,而想盡辦法且最好的轉換成寬高相同機關的映射模式。
說映射模式,不得不提視窗,視口,原點。不要太在意視窗,視口中文意思。我們更多的去記住它在繪圖中的含義更好。視窗,隻要想到和視窗有關系,一般就是隻的邏輯坐标,并表示目前的邏輯映射模式,說邏輯映射模式因該就是自己這麼說吧,不過可以讓我了解更清晰一點,因為我了解邏輯映射模式就是你自己設的,或者你沒設而目前預設的映射模式,它可能是裝置坐标映射。視口就是指的裝置坐标了。因為視口不會變。是以修改原點是多用視口修改。說到原點,其實我們要知道windows是怎麼做到把你寫的邏輯坐标,轉換到裝置坐标,你就知道為什麼要有視窗,視口,原點了。看下面的公式吧:xViewport=(xWindow-xWindowOrg)*xViewExt/xWinExt+xViewOrg
yViewport=(ywindow-ywindowOrg)*yViewExt/yWinExt+yViewOrg,其中xWindow-xWindowOrg是算出邏輯坐标位移差(點到原點舉例),xViewExt/xWinExt是得到一個邏輯坐标有多少個裝置坐标長度,那兩者相乘就得到了裝置坐标位移差,那在加上xViewOrg就得到真正在裝置上的坐标了。不要認為麻煩,這是非常有必要的,沒有這個公式,那麼繪圖會變得很單調,而且很複雜。因為設計出這些映射模式就是為了友善縮放和布局排版的。沒有他們相信你在列印啊,排版什麼地方會很痛苦。通過公式,可以看出原點有視窗原點和視口原點,他們就是視窗中的點和視口中的點對應的參考點。我們可以通過改變其中之一的原點,以達到我們改變我們的映射坐标系原點。将裝置原點往正方向(無論寬,還是高的正方向),映射坐标系原點會随着該方向進行相應的位移的偏移。将邏輯坐标系原點往改邏輯坐标系的正方向移動,會使得映射坐标系往相反的方向移動。因為公式裡面對邏輯坐标系原點是進行減的,而對裝置坐标系原點是進行加的。 而我說的映射坐标系就是你的邏輯坐标系。
視窗範圍和視口範圍,也不要用中文去想。看到上一點的那個公式,你就知道了,其實他們兩個和範圍沒太多關系,隻要有關系的是他們的比例。幾種常見的設定WM_ISOTROPIC方法,用同一事物去設定視窗範圍和視口範圍。這樣就能得到自己理想中的比例了。比如說,你想自己的邏輯坐标是1英尺3個邏輯機關。那麼你應該這麼寫:SetWindowExtEx(hdc,3,3,NULL);
SetViewportExtEx(hdc,GetDevicesCap(hdc,LOGPIXELSX),GetDevicesCaps(hdc,LOGPIXELSY),NULL);
GetDevicesCap(hdc,LOGPIXELSX)是得到1英寸有多少像素。這樣,因為設定視窗範圍和視口範圍都是參照1英寸的,是以windows就幫你實作了,你的3邏輯機關對應1英寸,其實是對應到windows計算出來的像素數,但這個像素數正好等于1英寸。
另外介紹有用的InvertRect,InvertRgn。這個是反轉區域色素的函數。黑變成白。和矩形相關的很多,如OffsetRect,SetRect,InsectRect,InflateRect,UnioRect,PtInRect。
區域是一個很重要的GDI對象,不想矩形那樣,就幾個坐标資料。區域首先是GDI對象,是以是一種資源,是以區域建立後都要删除。我們可以建立各種區域,矩形的,橢圓的,然後由矩形,橢圓以及其他區域進行各種區域操作得到的複雜區域。區域可以用于畫圖,可以用于畫圖。區域操作函數,CombineRgn(hDestRgn,hSrcRgn1,hSrcRgn2,iCombine)通過不同方式iCombine兩個區域的各種操作。但要注意這個函數中的hDestRgn可是單純用于承接結果。這個句柄必須是原來就有有效區域才可以,要不然會出錯。通過裁剪區域,然後将區域選進裝置環境,使得裝置重畫隻在裁剪後的區域内繪圖。以至于可以通過區域的屏蔽作用畫出很複雜的圖形。