日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

区域和裁减区域-Window GDI

發布時間:2025/3/20 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 区域和裁减区域-Window GDI 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

區域和裁減區域-Window GDI

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


區域的創建和選擇

一個應用程序通過調用指定形狀的函數來創建一個區域。下表顯示了創建標準圖形的函數

形狀

函數

矩形區域

CreateRectRgn, CreateRectRgnIndirect, SetRectRgn

圓角的矩形區域

CreateRoundRectRgn

橢圓區域

CreateEllipticRgn, CreateEllipticRgnIndirect

多邊形區域

CreatePolygonRgn, CreatePolyPolygonRgn

每個區域創建函數返回一個HANDLE來標示新創建的區域。一個應用程序可以通過調用SelectObject函數并將這個HANDLE作為第二個參數來將一個區域選擇進設備內容中。在一個區域被選擇進設備內容之后,應用程序可以對其執行各種操作。

區域操作

應用程序能夠合并區域、比較區域、著色和返回區域內部、給區域畫邊框、得到區域的大小和測試光標是否位于區域的范圍。

?

?

合并區域

應用程序通過調用CombineRgn函數來合并兩個區域。使用這個函數,應用程序能夠合并兩個區域的交集、兩個區域除交集之外的區域、兩個區域的并集等等。下面5個值定理了區域合并的類型。

意義

RGN_AND

兩個區域的交集

RGN_COPY

兩個區域的第一個區域作為新的區域

RGN_DIFF

第一個區域的部分減去兩個區域的交集

RGN_OR

兩個區域的并集

RGN_XOR

兩個區域的并集減去兩個區域的交集

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


比較區域

應用程序通過調用EqualRgn來比較兩個區域來判斷他們是否一樣。EqualRgn認為如果兩個區域在形狀和大小上相等就認為他們相等。

填充區域

應用程序可以通過調用FillRgn并提供一個刷子來填充某區域的內部。當程序調用FillRgn時,系統使用特定的設備內容的當前填充模式刷子來填充區域。有良種填充模式:交替的和纏繞的。程序能調用SetPolyFillMode函數來設置一個設備內容的填充模式。應用程序調用GetPolyFillMode函數來得到設備內容的當前填充模式。

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


交替模式

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

1.在區域內部選擇一個像素

2.延正X軸方向畫一條虛設的光線,從像素開始到無窮遠

3.每次光線和邊界線相交的,增加一個記數值

系統高亮那些記數值是奇數的像素。

?

?

纏繞模式

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

1.在畫每個邊界線的時候判斷方向

2.在區域的內部選擇一個像素

3.畫一條光線,延正X方向,從像素點到無窮遠

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

所有非0的像素被高亮。


AA

A

B

在交替模式下:

A發出的光線經過了三條邊界,那么記數值為3B經過了兩條邊界,記數值為2,所以A所在的區域為高亮,B所在的區域不是。

?

?

區域著色

應用程序使用當前選進設備內容的刷子來填充區域的內部,刷子通過PaintRgn函數來選擇的,這個函數使用當前的多邊形填充模式(交替和纏繞)

?

?

反轉區域

程序通過調用InvertRgn函數來使區域的顏色反色。在單色的顯示設備上,InvertRgn是白色像素變黑,黑色像素變白。在彩色屏幕上,這個反轉依賴于產生屏幕顏色的技術類型。

?

?

為區域增加框架

應用程序可以調用FrameRgn函數來為區域周圍畫一個邊界,并指定邊界的寬度和刷子的模式。

?

?

得到區域的矩形范圍

應用程序通過調用GetRgnBox函數來得到區域邊界矩形的大小。如果區域是規則的,GetRgnBox返回區域的大小;如果區域是橢圓形,函數返回包圍在橢圓周圍的最小矩形的大小,長邊的長度和橢圓的主軸相等,短邊和橢圓的次軸相同。如果區域是多邊形,GetRgnBox返回最小的包圍多邊形的矩形。

?

?

移動區域

應用程序調用OffsetRgn函數來移動區域。給定的延XY軸防線的偏移決定了左右上下移動的邏輯單位。

?

?

點擊測試區域

應用在區域上執行點擊測試來判斷當前光標位置的坐標。然后傳遞這些坐標和區域的HANDLEPtInRegion函數。光標的坐標可以由多種鼠標操作得到,例如WM_LBUTTONDOWNWM_LBUTTONUPWM_RBUTTONDOWNWM_RBUTTONUPPtInRegion函數的返回值指出當前光標位置是否在給定的區域內。

?

?

使用區域來裁減輸出

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

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

通過單擊Define Clip Region菜單,用戶能夠通過單擊鼠標左鍵并拖動鼠標來選擇一個裁減區域。當用戶拖動鼠標的時候,應用程序畫一個相對于新裁減區域的矩形。

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

本節提供下面的主題:

定義裁減區域

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

case WM_COMMAND:

????switch (wParam)

????{

?

????????case IDM_DEFINE:

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

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

在Define Clipping Region之后,用戶開始通過鼠標的單擊和拖動來畫矩形。

當用戶按下鼠標左鍵時,系統產生WM_LBUTTONDOWN消息,lParam參數包含了光標的位置,它對應于裁減區域矩形的左上角。程序處理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; }

當用戶拖動鼠標的時候,系統產生WM_MOUSEMOVE消息并存儲新的光標位置到lParam參數中。每次應用程序接收到WM_MOUSEMOVE消息時,它都刪除先前的矩形(如果存在的話)并通過PolyLine函數來畫一個新的區域,以矩形的四個角的坐標,程序執行下面的工作。

// 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. ???????//如果先前鼠標移動了,原來較小的右下角坐標到ptLowerRight ????????if (ptLowerRight.x) ????????{ ????????????ptTmp.x = ptLowerRight.x; ????????????ptTmp.y = ptLowerRight.y; ????????} ????????// Get the new coordinates of the clipping region's lower ????????// right corner. ????????//取得新的右下角的坐標 ????????ptsTmp = MAKEPOINTS(lParam); ????????ptLowerRight.x = (LONG) ptsTmp.x; ????????ptLowerRight.y = (LONG) ptsTmp.y; ????????// If previous mouse movement occurred, erase the original ????????// rectangle. ????????//如果鼠標已經移動了,刪除原來的矩形 ????????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菜單之后,應用程序使用用戶創建的裁減區域的矩形坐標,在定義裁減區域后,將它選進程序的設備內容中,程序重畫位圖,程序執行下面的工作:

// 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. //得到程序的客戶區矩形,并用白刷子填充 ????GetClientRect(hwnd, &rctTmp); ????FillRect(hdc, &rctTmp, GetStockObject(WHITE_BRUSH)); // Use the rect coordinates to define a clipping region. //使用rect的坐標來定義一個裁減區域 ????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; ????}

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。