图形基础---矩形、区域和剪裁

本文介绍了Windows图形编程中关于矩形、区域和剪裁的相关函数,包括FillRect、FrameRect、InvertRect等,详细阐述了如何创建、操作和使用这些图形元素。同时,通过示例解释了如何利用PeekMessage函数实现不间断地绘制随机矩形,并探讨了剪裁区域的概念和应用,如创建和组合剪裁区域,以及如何在图形绘制中应用剪裁区域进行限制。
摘要由CSDN通过智能技术生成
 

矩形、区域和剪裁

Windows包含了几种使用RECT(矩形)结构和「区域」的绘图函数。区域就是屏幕上的一块地方,它是矩形、多边形和椭圆的组合。

矩形函数

下面三个绘图函数需要一个指向矩形结构的指针:

FillRect (hdc, &rect, hBrush) ;
        
FrameRect (hdc, &rect, hBrush) ;
        
InvertRect (hdc, &rect) ;
        

在这些函数中,rect参数是一个RECT型态的结构,它包含有4个字段:left、top、right和bottom。这个结构中的坐标被当作逻辑坐标。

FillRect用指定画刷来填入矩形(直到但不包含right和bottom坐标),该函数不需要先将画刷选进设备内容。

FrameRect使用画刷画矩形框,但是不填入矩形。使用画刷画矩形看起来有点奇怪,因为对于我们所介绍过的函数(如Rectangle),其边线都是用目前画笔绘制的。FrameRect允许使用者画一个不一定为纯色的矩形框。该边界框为一个逻辑单位元宽。如果逻辑单位大于设备单位,则边界框将会为2个图素宽或者更宽。

InvertRect将矩形中所有图素翻转,1转换成0,0转换为1,该函数将白色区域转变成黑色,黑色区域转变为白色,绿色区域转变成洋红色。

Windows还提供了9个函数,使您可以更容易、更清楚地操作RECT结构。例如,要将RECT结构的四个字段设定为特定值,通常使用如下的程序段:

rect.left          = xLeft ;
        
rect.top           = xTop ;
        
rect.right         = xRight ;
        
rect.bottom        = xBottom ;
        

但是,通过呼叫SetRect函数,只需要一道叙述就可以得到同样的结果:

SetRect (&rect, xLeft, yTop, xRight, yBottom) ;
        

在您想要做以下事情之一时,可以很方便地选用其它8个函数:

  • 将矩形沿x轴和y轴移动几个单元:
     

OffsetRect (&rect, x, y) ;

  • 增减矩形的尺寸:
     

InflateRect (&rect, x, y) ;

  • 矩形各字段设定为0:
     

SetRectEmpty (&rect) ;

  • 将矩形复制给另一个矩形:
     

CopyRect (&DestRect, &SrcRect) ;

  • 取得两个矩形的交集:
     

IntersectRect (&DestRect, &SrcRect1, &SrcRect2) ;

  • 取得两个矩形的联集:
     

UnionRect (&DestRect, &SrcRect1, &SrcRect2) ;

  • 确定矩形是否为空:
     

bEmpty = IsRectEmpty (&rect) ;

  • 确定点是否在矩形内:
     

bInRect = PtInRect (&rect, point) ;

大多数情况下,与这些函数相同作用的程序代码很简单。例如,您可以用下列叙述来替代CopyRect函数呼叫:

DestRect = SrcRect ;
        

随机矩形

在图形系统中,有这么一个「永远」有人执行的有趣程序,它简单地使用随机的大小和色彩绘制一系列矩形。您可以在Windows中建立一个这样的程序,但是它并不像乍看起来那样容易编写。我希望您能认识到,您不能简单地在WM_PAINT消息中使用一个while(TRUE)循环。当然,它能够执行,但是程序将停止对其他消息的处理,同时,这个程序不能中止或者最小化。

一种可以接受的方法是设定一个Windows定时器,给窗口程序发送WM_TIMER消息(我将在 第八章中讨论定时器)。对于每条WM_TIMER消息,您使用GetDC取得一个设备内容,画一个随机的矩形,然后用ReleaseDC释放设备内容。但是这样又降低了程序的趣昧性,因为程序不能尽可能快地画随机矩形,它必须等待WM_TIMER消息,而这又依赖于系统时钟的分辨率。

在Windows中一定有很多「闲置时间」,在这个时间内,所有消息队列为空,Windows只停在一个小循环中等待键盘或者鼠标输入。我们能否在闲置时间内获得控制,绘制矩形,并且只在有消息加入程序的消息队列之后才释放控制呢?这就是PeekMessage函数的目的之一。下面是PeekMessage呼叫的一个例子:

PeekMessage (&msg, NULL, 0, 0, PM_REMOVE) ;
        

前面的四个参数(一个指向MSG结构的指针、一个窗口句柄、两个值指示消息范围)与GetMessage的参数相同。将第二、三、四个参数设定为NULL或0时,表明我们想让PeekMessage传回程序中所有窗口的所有消息。如果要将消息从消息队列中删除,则将PeekMessage的最后一个参数设定为PM_REMOVE。如果您不希望删除消息,那么您可以将这个参数设定为PM_NOREMOVE。这就是为什么Peek_Message是「偷看」而不是「取得」的原因,它使得程序可以检查程序的队列中的下一个消息,而不实际删除它。

GetMessage不将控制传回给程序,直到从程序的消息队列中取得消息,但是PeekMessage总是立刻传回,而不论一个消息是否出现。当消息队列中有一个消息时,PeekMessage的传回值为TRUE(非0),并且将按通常方式处理消息。当队列中没有消息时,PeekMessage传回FALSE(0)。

这使得我们可以改写普通的消息循环。我们可以将如下所示的循环:

while (GetMessage (&msg, NULL, 0, 0))
        
{
        
    TranslateMessage (&msg) ;
        
    DispatchMessage (&msg) ;
        
}
        
return msg.wParam ;
        

替换为下面的循环:

while (TRUE)
        
{
        
    if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
        
    {
        
            if (msg.message == WM_QUIT)
        
                   break ;
        
            TranslateMessage (&msg) ;
        
            DispatchMessage (&msg) ;
        
    }
        
    else
        
    {
        
            // 完成某些工作的其它行程序
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值