日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

区域和裁减区域-Window GDI

發(fā)布時(shí)間:2025/3/20 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 区域和裁减区域-Window GDI 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

區(qū)域和裁減區(qū)域-Window GDI

原文:http://blog.csdn.net/windcsn/article/details/492436


區(qū)域的創(chuàng)建和選擇

一個(gè)應(yīng)用程序通過調(diào)用指定形狀的函數(shù)來創(chuàng)建一個(gè)區(qū)域。下表顯示了創(chuàng)建標(biāo)準(zhǔn)圖形的函數(shù)

形狀

函數(shù)

矩形區(qū)域

CreateRectRgn, CreateRectRgnIndirect, SetRectRgn

圓角的矩形區(qū)域

CreateRoundRectRgn

橢圓區(qū)域

CreateEllipticRgn, CreateEllipticRgnIndirect

多邊形區(qū)域

CreatePolygonRgn, CreatePolyPolygonRgn

每個(gè)區(qū)域創(chuàng)建函數(shù)返回一個(gè)HANDLE來標(biāo)示新創(chuàng)建的區(qū)域。一個(gè)應(yīng)用程序可以通過調(diào)用SelectObject函數(shù)并將這個(gè)HANDLE作為第二個(gè)參數(shù)來將一個(gè)區(qū)域選擇進(jìn)設(shè)備內(nèi)容中。在一個(gè)區(qū)域被選擇進(jìn)設(shè)備內(nèi)容之后,應(yīng)用程序可以對(duì)其執(zhí)行各種操作。

區(qū)域操作

應(yīng)用程序能夠合并區(qū)域、比較區(qū)域、著色和返回區(qū)域內(nèi)部、給區(qū)域畫邊框、得到區(qū)域的大小和測試光標(biāo)是否位于區(qū)域的范圍。

?

?

合并區(qū)域

應(yīng)用程序通過調(diào)用CombineRgn函數(shù)來合并兩個(gè)區(qū)域。使用這個(gè)函數(shù),應(yīng)用程序能夠合并兩個(gè)區(qū)域的交集、兩個(gè)區(qū)域除交集之外的區(qū)域、兩個(gè)區(qū)域的并集等等。下面5個(gè)值定理了區(qū)域合并的類型。

意義

RGN_AND

兩個(gè)區(qū)域的交集

RGN_COPY

兩個(gè)區(qū)域的第一個(gè)區(qū)域作為新的區(qū)域

RGN_DIFF

第一個(gè)區(qū)域的部分減去兩個(gè)區(qū)域的交集

RGN_OR

兩個(gè)區(qū)域的并集

RGN_XOR

兩個(gè)區(qū)域的并集減去兩個(gè)區(qū)域的交集

下面圖形顯示了5種使用CombineRgn來操作正方形和圓合并的可能結(jié)果:


比較區(qū)域

應(yīng)用程序通過調(diào)用EqualRgn來比較兩個(gè)區(qū)域來判斷他們是否一樣。EqualRgn認(rèn)為如果兩個(gè)區(qū)域在形狀和大小上相等就認(rèn)為他們相等。

填充區(qū)域

應(yīng)用程序可以通過調(diào)用FillRgn并提供一個(gè)刷子來填充某區(qū)域的內(nèi)部。當(dāng)程序調(diào)用FillRgn時(shí),系統(tǒng)使用特定的設(shè)備內(nèi)容的當(dāng)前填充模式刷子來填充區(qū)域。有良種填充模式:交替的和纏繞的。程序能調(diào)用SetPolyFillMode函數(shù)來設(shè)置一個(gè)設(shè)備內(nèi)容的填充模式。應(yīng)用程序調(diào)用GetPolyFillMode函數(shù)來得到設(shè)備內(nèi)容的當(dāng)前填充模式。

下圖描述了良種填充模式,一種使用交替模式,另一種使用纏繞模式。


交替模式

在交替模式下,為了判斷那些像素需要高亮,執(zhí)行下面的測試:

1.在區(qū)域內(nèi)部選擇一個(gè)像素

2.延正X軸方向畫一條虛設(shè)的光線,從像素開始到無窮遠(yuǎn)

3.每次光線和邊界線相交的,增加一個(gè)記數(shù)值

系統(tǒng)高亮那些記數(shù)值是奇數(shù)的像素。

?

?

纏繞模式

為了判斷纏繞模式下那些像素需要高亮,需要執(zhí)行下面測試:

1.在畫每個(gè)邊界線的時(shí)候判斷方向

2.在區(qū)域的內(nèi)部選擇一個(gè)像素

3.畫一條光線,延正X方向,從像素點(diǎn)到無窮遠(yuǎn)

4.每次光線與邊界線在正Y部分正交的時(shí)候,增加記數(shù)值,如果在Y負(fù)方向,減記數(shù)值。

所有非0的像素被高亮。


AA

A

B

在交替模式下:

A發(fā)出的光線經(jīng)過了三條邊界,那么記數(shù)值為3B經(jīng)過了兩條邊界,記數(shù)值為2,所以A所在的區(qū)域?yàn)楦吡?#xff0c;B所在的區(qū)域不是。

?

?

區(qū)域著色

應(yīng)用程序使用當(dāng)前選進(jìn)設(shè)備內(nèi)容的刷子來填充區(qū)域的內(nèi)部,刷子通過PaintRgn函數(shù)來選擇的,這個(gè)函數(shù)使用當(dāng)前的多邊形填充模式(交替和纏繞)

?

?

反轉(zhuǎn)區(qū)域

程序通過調(diào)用InvertRgn函數(shù)來使區(qū)域的顏色反色。在單色的顯示設(shè)備上,InvertRgn是白色像素變黑,黑色像素變白。在彩色屏幕上,這個(gè)反轉(zhuǎn)依賴于產(chǎn)生屏幕顏色的技術(shù)類型。

?

?

為區(qū)域增加框架

應(yīng)用程序可以調(diào)用FrameRgn函數(shù)來為區(qū)域周圍畫一個(gè)邊界,并指定邊界的寬度和刷子的模式。

?

?

得到區(qū)域的矩形范圍

應(yīng)用程序通過調(diào)用GetRgnBox函數(shù)來得到區(qū)域邊界矩形的大小。如果區(qū)域是規(guī)則的,GetRgnBox返回區(qū)域的大小;如果區(qū)域是橢圓形,函數(shù)返回包圍在橢圓周圍的最小矩形的大小,長邊的長度和橢圓的主軸相等,短邊和橢圓的次軸相同。如果區(qū)域是多邊形,GetRgnBox返回最小的包圍多邊形的矩形。

?

?

移動(dòng)區(qū)域

應(yīng)用程序調(diào)用OffsetRgn函數(shù)來移動(dòng)區(qū)域。給定的延XY軸防線的偏移決定了左右上下移動(dòng)的邏輯單位。

?

?

點(diǎn)擊測試區(qū)域

應(yīng)用在區(qū)域上執(zhí)行點(diǎn)擊測試來判斷當(dāng)前光標(biāo)位置的坐標(biāo)。然后傳遞這些坐標(biāo)和區(qū)域的HANDLEPtInRegion函數(shù)。光標(biāo)的坐標(biāo)可以由多種鼠標(biāo)操作得到,例如WM_LBUTTONDOWNWM_LBUTTONUPWM_RBUTTONDOWNWM_RBUTTONUPPtInRegion函數(shù)的返回值指出當(dāng)前光標(biāo)位置是否在給定的區(qū)域內(nèi)。

?

?

使用區(qū)域來裁減輸出

本節(jié)包含一個(gè)簡單的例子,介紹你怎么樣使用區(qū)域是用戶可以定義這樣輸出客戶區(qū)域的一部分。用作這個(gè)目的的區(qū)域被叫做裁減區(qū)域。

本節(jié)的例子,用戶可以通過程序來抓獲整個(gè)桌面為一位圖,但能保存圖象的一部分作為BMP文件。

通過單擊Define Clip Region菜單,用戶能夠通過單擊鼠標(biāo)左鍵并拖動(dòng)鼠標(biāo)來選擇一個(gè)裁減區(qū)域。當(dāng)用戶拖動(dòng)鼠標(biāo)的時(shí)候,應(yīng)用程序畫一個(gè)相對(duì)于新裁減區(qū)域的矩形。

通過單擊Clip菜單,用戶能夠重畫指定矩形邊界內(nèi)的圖像獨(dú)立部分。

本節(jié)提供下面的主題:

定義裁減區(qū)域

當(dāng)用戶單擊Define Clip Region時(shí),系統(tǒng)產(chǎn)生一個(gè)WM_COMMAND消息。該消息的wParam參數(shù)包含了程序自定義常量IDM_DEFINE,這指出用戶選擇了菜單,程序通過處理該輸出并設(shè)置布爾變量fDefineRegion,如下面的代碼:

case WM_COMMAND:

????switch (wParam)

????{

?

????????case IDM_DEFINE:

????????????fDefineRegion = TRUE;

????????????break;

在Define Clipping Region之后,用戶開始通過鼠標(biāo)的單擊和拖動(dòng)來畫矩形。

當(dāng)用戶按下鼠標(biāo)左鍵時(shí),系統(tǒng)產(chǎn)生WM_LBUTTONDOWN消息,lParam參數(shù)包含了光標(biāo)的位置,它對(duì)應(yīng)于裁減區(qū)域矩形的左上角。程序處理WM_LBUTTONDOWN消息如下:

// These variables are required for clipping. static POINT ptUpperLeft; static POINT ptLowerRight; static POINT aptRect[5]; static POINT ptTmp; static POINTS ptsTmp; static BOOL fDefineRegion; static BOOL fRegionExists; static HRGN hrgn; static RECT rctTmp; int i; switch (message) { ????case WM_LBUTTONDOWN: ????????if (fDefineRegion) ????????{ ????????// Retrieve the new upper left corner. ????????????ptsTmp = MAKEPOINTS(lParam); ????????????ptUpperLeft.x = (LONG) ptsTmp.x; ????????????ptUpperLeft.y = (LONG) ptsTmp.y; ????????} ????????if (fRegionExists) ????????{ ????????????// Erase the previous rectangle. ????????????hdc = GetDC(hwnd); ????????????SetROP2(hdc, R2_NOTXORPEN); ????????????if (!Polyline(hdc, (CONST POINT *) aptRect, 5)) ????????????????errhandler("Polyline Failed", hwnd); ????????????ReleaseDC(hwnd, hdc); ????????????// Clear the rectangle coordinates. ????????????for (i = 0; i < 4; i++) ????????????{ ????????????????aptRect[i].x = 0; ????????????????aptRect[i].y = 0; ????????????} ????????????// Clear the temporary point structure. ????????????ptTmp.x = 0; ????????????ptTmp.y = 0; ????????????// Clear the lower right coordinates. ????????????ptLowerRight.x = 0; ????????????ptLowerRight.y = 0; ????????????// Reset the flag. ????????????fRegionExists = FALSE; ????????????fDefineRegion = TRUE; ????????????// Retrieve the new upper left corner. ????????????ptsTmp = MAKEPOINTS(lParam); ????????????ptUpperLeft.x = (LONG) ptsTmp.x; ????????????ptUpperLeft.y = (LONG) ptsTmp.y; ????????} ????break; }

當(dāng)用戶拖動(dòng)鼠標(biāo)的時(shí)候,系統(tǒng)產(chǎn)生WM_MOUSEMOVE消息并存儲(chǔ)新的光標(biāo)位置到lParam參數(shù)中。每次應(yīng)用程序接收到WM_MOUSEMOVE消息時(shí),它都刪除先前的矩形(如果存在的話)并通過PolyLine函數(shù)來畫一個(gè)新的區(qū)域,以矩形的四個(gè)角的坐標(biāo),程序執(zhí)行下面的工作。

// These variables are required for clipping. static POINT ptUpperLeft; static POINT ptLowerRight; static POINT aptRect[5]; static POINT ptTmp; static POINTS ptsTmp; static BOOL fDefineRegion; static BOOL fRegionExists; static HRGN hrgn; static RECT rctTmp; int i; switch (message) { ????case WM_MOUSEMOVE: ????if (wParam & MK_LBUTTON && fDefineRegion) ????{ ????????// Get a window DC. ????????hdc = GetDC(hwnd); ????????if (!SetROP2(hdc, R2_NOTXORPEN)) ????????????errhandler("SetROP2 Failed", hwnd); ????????// If previous mouse movement occurred, store the original ????????// lower right corner coordinates in a temporary structure. ???????//如果先前鼠標(biāo)移動(dòng)了,原來較小的右下角坐標(biāo)到ptLowerRight ????????if (ptLowerRight.x) ????????{ ????????????ptTmp.x = ptLowerRight.x; ????????????ptTmp.y = ptLowerRight.y; ????????} ????????// Get the new coordinates of the clipping region's lower ????????// right corner. ????????//取得新的右下角的坐標(biāo) ????????ptsTmp = MAKEPOINTS(lParam); ????????ptLowerRight.x = (LONG) ptsTmp.x; ????????ptLowerRight.y = (LONG) ptsTmp.y; ????????// If previous mouse movement occurred, erase the original ????????// rectangle. ????????//如果鼠標(biāo)已經(jīng)移動(dòng)了,刪除原來的矩形 ????????if (ptTmp.x) ????????{ ????????????aptRect[0].x = ptUpperLeft.x; ????????????aptRect[0].y = ptUpperLeft.y; ????????????aptRect[1].x = ptTmp.x; ????????????aptRect[1].y = ptUpperLeft.y; ????????????aptRect[2].x = ptTmp.x; ????????????aptRect[2].y = ptTmp.y; ????????????aptRect[3].x = ptUpperLeft.x; ????????????aptRect[3].y = ptTmp.y; ????????????aptRect[4].x = aptRect[0].x; ????????????aptRect[4].y = aptRect[0].y; ????????????if (!Polyline(hdc, (CONST POINT *) aptRect, 5)) ????????????????errhandler("Polyline Failed", hwnd); ????????} ????????aptRect[0].x = ptUpperLeft.x; ????????aptRect[0].y = ptUpperLeft.y; ????????aptRect[1].x = ptLowerRight.x; ????????aptRect[1].y = ptUpperLeft.y; ????????aptRect[2].x = ptLowerRight.x; ????????aptRect[2].y = ptLowerRight.y; ????????aptRect[3].x = ptUpperLeft.x; ????????aptRect[3].y = ptLowerRight.y; ????????aptRect[4].x = aptRect[0].x; ????????aptRect[4].y = aptRect[0].y; ????????if (!Polyline(hdc, (CONST POINT *) aptRect, 5)) ?????????????errhandler("Polyline Failed", hwnd); ????????ReleaseDC(hwnd, hdc); ????} ????break;

?

?

裁減輸出

在用戶選擇Clip菜單之后,應(yīng)用程序使用用戶創(chuàng)建的裁減區(qū)域的矩形坐標(biāo),在定義裁減區(qū)域后,將它選進(jìn)程序的設(shè)備內(nèi)容中,程序重畫位圖,程序執(zhí)行下面的工作:

// These variables are required for clipping. static POINT ptUpperLeft; static POINT ptLowerRight; static POINT aptRect[5]; static POINT ptTmp; static POINTS ptsTmp; static BOOL fDefineRegion; static BOOL fRegionExists; static HRGN hrgn; static RECT rctTmp; int i; case WM_COMMAND: ????switch (wParam) ????{ ????case IDM_CLIP: ????hdc = GetDC(hwnd); ????// Retrieve the application's client rectangle and paint // with the default (white) brush. //得到程序的客戶區(qū)矩形,并用白刷子填充 ????GetClientRect(hwnd, &rctTmp); ????FillRect(hdc, &rctTmp, GetStockObject(WHITE_BRUSH)); // Use the rect coordinates to define a clipping region. //使用rect的坐標(biāo)來定義一個(gè)裁減區(qū)域 ????hrgn = CreateRectRgn(aptRect[0].x, aptRect[0].y, ????????aptRect[2].x, aptRect[2].y); ????SelectClipRgn(hdc, hrgn); // Transfer (draw) the bitmap into the clipped rectangle. //將位圖畫到裁減矩形中 ????BitBlt(hdc, ???????0, 0, ???????bmp.bmWidth, bmp.bmHeight, ???????hdcCompatible, ???????0, 0, ???????SRCCOPY); ????ReleaseDC(hwnd, hdc); ????break; ????}

總結(jié)

以上是生活随笔為你收集整理的区域和裁减区域-Window GDI的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。