建立和绘制区域

一个区域是对显示器一块空间的描叙,这个空间可以是矩形,多边形和椭圆的组合。

可以使用区域进行绘图或者剪裁。将区域选入设备环境,就可以使用这个区域来剪裁(也就是说,将绘制动作限制在客户区的一个特定部分)。同画笔和画刷一样,区域也是 GDI 对象,应当通过调用 DeleteObject() 拉力删除所建立的区域。

当建立一个区域时,Windows 返回一个类型为 HRGN 的区域句柄。最简单的区域类型是一个矩形。

 

建立一个矩形区域:
hRgn =  CreateRectRgn(xLeft, yTop, xRight, yBottom) ; 或者  hRgn = CreateRectRgn(&rect) ;

返回值:如果函数成功,返回该区域的句柄。如果函数失败,返回NULL。

 

建立椭圆区域:
 hRgn =  CreateEllipticRgn(xLeft, yTop, xRight, yBottom) ; 或者 hRgn = CreateEllipticRgnIndirect(&rect) ;

返回值:如果函数成功,返回该区域的句柄。如果函数失败,返回NULL。

 

建立圆角矩形区域:

hRgn = CreateRoundRectRgn(xLeft, yTop, xRight, yBottom, Width, Height) ;

返回值:如果函数成功,返回该区域的句柄。如果函数失败,返回NULL。
 
建立多边矩形区域:
hRgn = CreatePolygonRgn(&point, iCount, iPolyFillMode) ;
功能:创建一个由一系列点围成的区域。
iPolyFillMode 这个参数可以是 ALTERNATE 或者是 WINDING。
模式ALTERNATE:
其从封闭区域中的一个点向无穷远处水平画一条射线,只有当该射线穿越奇数条边框线时,封闭区域才被填充。
如为偶数,则不填充该区域;
模式WINDING:
如为奇数,填充该区域;
如为偶数则要根据边框线的方向来判断:如果穿过的边框线在不同方向的边框线数目相等,则不填充,如不等,则填充。
返回值:如果函数成功,返回该区域的句柄。如果函数失败,返回 NULL。
 
CombineRgn() 介绍:
     功能:将两个区域组合为一个新区域。
     函数原型:int CombineRgn(HRGN  hDestRgn, HRGN hSrcRgn1, HRGN hSrcRgn2, int  iCombineMode) ;
     参数:
        hDestRgn:包含组合结果的区域句柄。
        hSrcRgn1:源区域1。
        hSrcRgn2:源区域2。
        iCombineMode:组合两区域的方法。可设为下述常数。
                                    RGN_AND:hDestRgn被设置为两个源区域的交集(集合中的交集)。
                                    RGN_COPY:hDestRgn被设置为hSrcRgn1的拷贝。
                                    RGN_DIFF:hDestRgn被设置为hSrcRgn1与hSrcRgn2相减后的区域(集合中的差集)。
                                    RGN_OR:hDestRgn被设置为两个区域的并集(集合中的并集)。
                                    RGN_XOR:hDestRgn被设置为两个区域的异或操作后的区域(集合中的异或操作)。
     返回值:下列常数之一:
                    COMPLEXREGION:区域有互相交叠的边界。
                    SIMPLEREGION:区域边界没有互相交叠。
                    NULLREGION:区域为空。
                    ERRORAPI:不能创建组合区域。
(注意:这三个区域句柄都必须有效,但是函数调用后 hDestRgn 先前描叙的区域被销毁了)

 

一旦有了一个区域的句柄,就可以使用下面四个绘图函数了:

FrameRgn(hdc, hRgn, hBrush,Width, Height) ;

功能:用 指定刷子 围绕 指定区域 画一个外框。

返回值:如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。

 

FillRgn(hdc, hRgn, hBrush) ;

功能:用 指定刷子 填充 指定区域。

返回值:如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。

 

InvertRgn(hdc, hRgn) ;

功能:翻转 指定区域 内所有的像素,将 1 变为 0,0 变为 1。(例:最直观的颠倒黑白...等等)。

返回值:如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。

 

PaintRgn(hdc, hRgn) ;

功能:使用当前被选入设备环境的画刷填充区域。

返回值:如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。

 

用完一个区域后,可以用与删除其他 GDI 对象相同的函数来删除它:
DeleteObject(hRgn) ;

 

区域与区域的剪裁:

区域在剪裁中扮演者重要角色。InvalidRect() 使显示的矩形区域无效,并产生一个 WW_PAINT 消息。

可以通过调用 GetUpdateRect() 获取无效矩形的坐标,并且使用 ValidateRect() 使客户区的矩形有效.

类似的有:InvalidateRgn() 和 ValidateRgn()。

可以通过将一个区域选入到设备环境来创建自己的剪裁区域,将区域选入设备环境可以使用

SelectObject(hdc, hRgn) ;  或   SelectClipRgn(hdc, hRgn) ;

还有几个操纵剪裁区域的函数,例如 ExcludeClipRect() 用来从剪裁区域中去除一个矩形;

InterSectClipRect() 用来建立一个新的剪裁区域,这个新的剪裁区域是先前的剪裁区域和某个矩形的交集;

OffsetClipRgn() 用来把一个剪裁区域移动到客户区的另外一部分。

 

InvalidateRect(hWnd, &rect, BOOL) ;

功能:该函数向指定的窗体更新区域添加一个矩形,然后窗口客户区域的这一部分将被重新绘制。

参数:如果第一个参数为 NULL,则系统将在函数返回前重新绘制所有的窗口,

           然后发送 WM_ERASEBKGND 和 WM_PAINT 给窗口过程处理函数。

           如果第二个参数为 NULL,全部的窗口客户区域将被增加到更新区域中。

           第三个参数是 BOOL 型变量。指出无效矩形被标记为有效后,是否重画该区域。

返回值:函数成功则返回非零值,否则返回零值。

 

GetupdateRect(hWnd, &rect, BOOL) ;

功能:获取完全封闭更新区域的最小矩形的坐标。

参数:BOOL 型变量。指定更新区域中的背景是否要被擦除。

返回值:如果更新区域不为空,则返回值为非零值;否则为0。

 

ValidateRect(hWnd, &rect) ;

功能:该函数更新指定窗口的无效矩形区域,使之有效。

返回值:函数成功则返回非零值,否则返回零值。

 

InvalidateRgn(hWnd, hRgn, BOOL) ;

功能:通过添加一个区域到一个窗口的更新区域中来使指定矩形的客户区域无效;

          这个无效的区域和所有更新区域中的其他区域将被标记用来在下一个WM_PAINT消息发生的时候描绘。

参数:BOOL 型变量:说明当更新区域被处理的时候更新区域内的背景是否要擦除。

返回值:返回值总是 0。

 

ValidateRgn(hWnd, hRgn) ;

功能:激活窗口中指定区域,把它从刷新区移走。

返回值:函数成功则返回非零值,否则返回零值。

 

ExcludeClipRect(hdc, xLeft, yTop, xRight, yBottom) ;

功能:函数的功能是创建一个新的剪切区域,该区域由一个现存的剪切区域减去一个特定的矩形区域而构成。

返回值:该返回值表明了新的剪切区域的复杂度,它可是如下几种形式:(int 型)

              NULLREGION:剪切区域为空;
              SIMPLEREGION:剪切区域是单个矩形;
              COMPIEXREGION:剪切区域有多个矩形;
              ERROR:剪切区域创建失败
              (注释:矩形的最下边和最右边并不排除在剪切区域之外)
 
InterSectClipRect(hdc, xLeft, yTop, xRight, yBottom) ;

功能:该函数创建了一个新的剪切区域,该区域是当前剪切区域和一个特定矩形的交集。

返回值:返回值表明了新剪切区域的类型。(int 型)
               NULL REGION:区域为空;
               SIMPLEREGION:区域为单个矩形。
               CoupIExREGION:区域为多个矩形;
               ERROR:发生错误(当前的剪切区域不变影响)。
               (注释:给定矩形的最下边和最右边不包括在剪切区域。)
 
OffsetClipRgn(hdc, ixOffset, iyOffset) ;
功能:按指定的位移,移动设备上下文环境的剪切区域。
返回值:返回值表明了新剪切区域的类型。(int 型)
               NULL REGION:区域为空;
               SIMPLEREGION:区域为单个矩形。
               CoupIExREGION:区域为多个矩形;
               ERROR:发生错误(当前的剪切区域不变影响)。
               (注释:给定矩形的最下边和最右边不包括在剪切区域。)
 

 

CLOVER 程序:

#include <windows.h>
#include <math.h>
#define TWO_PI (2.0 * 3.14159)
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
     static TCHAR szAppName[] = TEXT ("Clover") ;
     HWND         hwnd ;
     MSG          msg ;
     WNDCLASS     wndclass ;
     
     wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
     wndclass.lpfnWndProc   = WndProc ;
     wndclass.cbClsExtra    = 0 ;
     wndclass.cbWndExtra    = 0 ;
     wndclass.hInstance     = hInstance ;
     wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
     wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
     wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
     wndclass.lpszMenuName  = NULL ;
     wndclass.lpszClassName = szAppName ;
     
     if (!RegisterClass (&wndclass))
     {
          MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
     }
     
     hwnd = CreateWindow (szAppName, TEXT ("Draw a Clover"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
     
     ShowWindow (hwnd, iCmdShow) ;
     UpdateWindow (hwnd) ;
     
     while (GetMessage (&msg, NULL, 0, 0))
     {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     }
     return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
     static HRGN hRgnClip ;
     static int  cxClient, cyClient ;
     double      fAngle, fRadius ;
     HCURSOR     hCursor ;
     HDC         hdc ;
     HRGN        hRgnTemp[6] ;
     int         i ;
     PAINTSTRUCT ps ;
     
     switch (iMsg)
     {
     case WM_SIZE:
          cxClient = LOWORD (lParam) ;
          cyClient = HIWORD (lParam) ;
          
          hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
          ShowCursor (TRUE) ;
          
          if (hRgnClip)
               DeleteObject (hRgnClip) ;
          
          hRgnTemp[0] = CreateEllipticRgn (0, cyClient / 3,
                                           cxClient / 2, 2 * cyClient / 3) ;
          hRgnTemp[1] = CreateEllipticRgn (cxClient / 2, cyClient / 3,
                                           cxClient, 2 * cyClient / 3) ;
          hRgnTemp[2] = CreateEllipticRgn (cxClient / 3, 0,
                                           2 * cxClient / 3, cyClient / 2) ;
          hRgnTemp[3] = CreateEllipticRgn (cxClient / 3, cyClient / 2,
                                           2 * cxClient / 3, cyClient) ;
          hRgnTemp[4] = CreateRectRgn (0, 0, 1, 1) ;
          hRgnTemp[5] = CreateRectRgn (0, 0, 1, 1) ;
          hRgnClip    = CreateRectRgn (0, 0, 1, 1) ;
          
          CombineRgn (hRgnTemp[4], hRgnTemp[0], hRgnTemp[1], RGN_OR) ;
          CombineRgn (hRgnTemp[5], hRgnTemp[2], hRgnTemp[3], RGN_OR) ;
          CombineRgn (hRgnClip,    hRgnTemp[4], hRgnTemp[5], RGN_XOR) ;
          
          for (i = 0 ; i < 6 ; i++)
               DeleteObject (hRgnTemp[i]) ;
          
          SetCursor (hCursor) ;
          ShowCursor (FALSE) ;
          return 0 ;
          
     case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
          
          SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;
          SelectClipRgn (hdc, hRgnClip) ;
          
          fRadius = _hypot (cxClient / 2.0, cyClient / 2.0) ;
          
          for (fAngle = 0.0 ; fAngle < TWO_PI ; fAngle += TWO_PI / 360)
          {
               MoveToEx (hdc, 0, 0, NULL) ;
               LineTo (hdc, (int) ( fRadius * cos (fAngle) + 0.5),
                            (int) (-fRadius * sin (fAngle) + 0.5)) ;
          }
          EndPaint (hwnd, &ps) ;
          return 0 ;
          
     case WM_DESTROY:
          DeleteObject (hRgnClip) ;
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}

 

posted @ 2018-07-17 09:51  M-Anonymous  阅读(959)  评论(0)    收藏  举报