Win32矩形的特殊操作和区域的创建、裁剪

一、矩形的一些特殊操作API函数

矩形是我们绘图时常用的一种图形,所以掌握更多好用、详细的矩形操作API函数
显得尤为重要了。下面介绍一些常用矩形操作函数:

1.SetRect函数-------(赋值)指定矩形的坐标

BOOL SetRect(LPRECT lprc,  // 指针,所要设置的矩形
             int xLeft,    // 指定矩形左上角的X坐标。
             int yTop,     // 指定矩形左上角的Y坐标。
             int xRight,   // 指定矩形右下角的X坐标。
             int yBottom); // 指定矩形右下角的Y坐标。

2.FillRect函数-------绘制填充矩形
用指定的画刷填充矩形,此函数包括矩形的左上边界,但不包括矩形的右下边界

int FillRect(HDC hdc, 
             CONST RECT *lprc,  //将填充矩形的指针
             HBRUSH hbr);      // 画刷句柄

3.FrameRect函数-------绘制矩形边框、无填充
用画刷而不用画笔的好处就是可以使用抖动色

int FrameRect(HDC hdc, CONST RECT *lprc, HBRUSH hbr);
举例 : FrameRect( hdc, &rect, hBrush ); 

4.InvertRect函数-------将矩形区域中所有像素点反转
二进制位01反转,即变成相反色(黑变白、白变黑、绿变洋红)

BOOL Invertrect(HDC hdc, CONST RECT *lprc);
举例 :InvertRect( hdc, &rect ); 

5.OffsetRect函数-------移动矩形,将改变坐标数据

BOOL OffsetRect(LPRECT lprc,    // 矩形指针
                int dx,         // 横向偏移量,左负右正
                int dy );       // 纵向偏移量,上负下正

6.InflateRect函数-------增大或减小指定矩形的宽和高

BOOL InflateRect(LPRECT lprc,   // 矩形指针
                 int dx,        // X轴,负为减少,正为增加
                 int dy);       // 轴,负为减少,正为增加

7.SetRectEmpty函数-------将矩形设为空矩形

BOOL SetRectEmpty( LPRECT lprc );

8.CopyRect函数-------复制矩形

BOOL CopyRect( LPRECT lprcDst,        // 目标矩形
               CONST RECT* lprcSrc);  // 源矩形

9.IntersectRect函数-------求两个源矩形的相交矩形

BOOL IntersectRect (LPCRECT lprcDst,    // 相交矩形
                    LPCRECT lpRect1,    // 源矩形1
                    LPCRECT lpRect2 );  // 源矩形2

10.UnionRect函数-------求两个源矩形的相并矩形

实例 :UnionRect( &DestRect, &SrcRect1, &SrcRect2 ); 
       // 结果是能包含两个Src的最小面积矩形

11.IsRectEmpty函数-------判断是否为空矩形

实例 :IsRectEmpty( &rect );

12.PtInRect函数-------判断点是否在矩形内

BOOLPtInRect(CONSTRECT*lprc,  // 矩形指针
             POINTpt);        // 点指针

应用:随机矩形

本例将展示一个在程序等待消息输入的空闲阶段显示随机矩形的案例;

PeekMessage介绍:

我们不能在WM_PAINT消息响应中利用while ( TRUE )循环来产生随机矩形,否则程序将停止对其它消息的响应,但是这里我们不用计时器来实现改程序;
程序的空闲时间:就是指用户不操作该程序从而程序也不会收到消息进行响应发生动作,这段时间即为空闲时间,空闲时间的特征就是消息队列为空!

利用PeekMessage查看消息队列是否为空:

BOOL PeekMessage( LPMSG lpMsg, HWND hWnd , UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg );

该函数和GetMessage的参数一样,只不过还多了一个操作选项,GetMessage函数时直接从队头取走一个消息(注意!是取走,就相当于将队头消息从队列中删除了),而PeekMessage只是偷看,即看一下队列中是否有消息(也是查看队头消息,并将该消息复制到第一个参数msg中),如果有消息则返回非0,无消息(即队列为空)则返回0,当然,查看完之后也可以和GetMessage一样将消息从队头取走(即删掉),这就是wRemoveMsg选项的作用,PM_REMOVE选项就和GetMessage函数的作用一样了(只不过返回值意义不一样而已),而PM_NOREMOVE则表示只偷看但不删除;
和GetMessage的共性:都不能删除队列中的WM_PAINT消息,WM_PAINT消息的删除只能通过Validate函数或者BeginPaint函数将无效区域有效化才能删除!即WM_PAINT的响应!使用PeekMessage函数的场合:在程序空闲时还要做一些其它任务的场合使用,

使用模板为:

while ( TRUE )
{
	if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
	{ // 队列中有消息
		if ( WM_QUIT == msg.message ) break; // 要判断是否退出
 
		TranslateMessage( &msg );
		DispatchMessage( &msg );
	}
	else
	{ 
	     // 程序空闲执行的功能代码。
	}


二、区域的创建、裁剪

区域介绍:

一个区域是对显示器一块空间的描述,这个空间可以是矩形、多边形和椭圆的组合等。我们可以在区域内 绘图或裁剪,将区域选入设备环境,就可以使用这个区域来裁剪(也就是将绘制限制在这区域内,只在裁剪区域里绘制)。区域也是GDI对象六大GDI对象之一,DeleteObject函数进行释放。也需要通过调用这个区域有程序员来创建、想要的大小、想要的形状、你可以在这个区域里面随心所欲填充图形,同时他也可以缩小、以及放大等等、还可以将多个区域进行组合、进行逻辑运算。

1.区域的创建

区域类型为 HRGN

矩形区域创建:CreateRectRgn函数和 CreateRectRgnIndirect函数和CreateRoundRectRgn函数

// 矩形区域
HRGN hRgn = CreateRectRgn( xLeft, yTop, xRight, yBottom );
HRGN hRgn = CreateRectRgnIndirect( &rect );

//圆角矩形区域
HRGN hRgn = CreateRoundRectRgn( xLeft, yTop, xRight, yBottom ,nWidthEllipse,nHeightEllipse);

椭圆区域创建:CreateEllipticRgn函数和 CreateRectRgnIndirect函数

// 椭圆区域
HRGN hRgn = CreateEllipticRgn( xLeft, yTop, xRight, yBottom );
HRGN hRgn = CreateRectRgnIndirect( &rect );

多边形区域创建:CreatePolygonRgn函数和 CreatePolyPolygonRgn函数

// 创建一个多边形区域
BOOL CreatePolygonRgn(LPPOINT lpPoints,   // 点数组的指针
                      int nCount,         // 多边形的点数
                      int nMode);         // 多边形填充模式,ALTERNATE或者WINDING
//创建由多个多边形构成的区域
HRGN hRgn = CreatePolyPolygonRgn( LPPOINT lpPoints,   // 点数组的指针
                                  lpPolyCounts        // 每个封闭多边形的点数
                                  int nCount,         // 多边形的点数
                                  int nMode);         // 多边形填充模式,ALTERNATE或者WINDING

填充区域:FillRgn函数

FillRgn(hdc,      // 设备DC
        hRgn,     // 区域句柄
        hbrush);  // 画刷句柄

绘制区域边框:

FrameRgn(hdc,      // 设备DC
         hRgn,     // 区域句柄
         hbrush);  // 画刷句柄

2.区域的合并: CombineRgn函数

将两个区域组合为一个新区域。
在使用CombineRgn函数合并之前需要创建一个空区域,也就是初始化,用来接收两个区域合并后的新区域。

// 创建空区域
HRGN hRgn=CreateRectRgn(0,0,1,1);  // 所创建的刚好为一个像素大小,节省空间
int CombineRgn( hDestRgn,     // 组合结果的区域句柄
                hSrcRgn1,     // 源区域1
                hSrcRgn2,     // 源区域2
                fnCombineMode );  // 组合两区域的方式,有以下几种值:
含义
RGN_AND hDestRgn被设置为两个源区域的交集(集合中的交集)
RGN_COPY hDestRgn被设置为hSrcRgn1的拷贝
RGN_DIFF hDestRgn被设置为hSrcRgn1与hSrcRgn2相减后的区域(集合中的差集)
RGN_OR hDestRgn被设置为两个区域的并集(集合中的并集)
RGN_XOR hDestRgn被设置为两个区域的异或操作后的区域(集合中的异或操作)

[返回值]下列常数之一:
COMPLEXREGION:区域有互相交叠的边界
SIMPLEREGION:
区域边界没有互相交叠
NULLREGION:区域为空
ERRORAPI:不能创建组合区域


3.区域的裁剪

区域裁剪就是将绘图范围限制在此区域内,超出部分不能绘制。

  1. 可以使用InvalidateRgn( hWnd, hRgn, bErase )和ValidateRgn( hWnd, hRgn )来将WM_PAINT的作用范围限制在指定的区域内部;

  2. 也可以通过SelectObject( hdc, hRgn )或者SelectClipRgn( hdc, hRgn )将绘制范围限制在剪裁区域;

  3. 可以对被选入环境中的剪裁区域进行修改,如:

// 从现有的被选入环境中的剪裁区域中除去指定的矩形部分
ExcludeClipRect( hdc, xLeft, yTop, xRight, yBottom );

// 将现有的被选入环境中的剪裁区域和指定的矩形合并
IntersectClipRect( hdc, xLeft, yTop, xRight, yBottom );

// 将现有的剪裁区域朝x方向或y方向位移
OffsetClipRgn( hdc, x, y );

好困啊!!!!!不行了,赶快躺床睡,眼睛瞎了~

发布了30 篇原创文章 · 获赞 37 · 访问量 5500

猜你喜欢

转载自blog.csdn.net/qq_45021180/article/details/99700901
今日推荐