码迷,mamicode.com
首页 > 其他好文 > 详细

第5章 绘图基础_5.6 矩形、区域和剪裁

时间:2015-07-18 08:24:39      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:

 5.6.1 处理矩形

(1)绘图函数

绘图函数

说明

FillRect(hdc,&rect,hBrush)

不用先将画刷选入设备环境

FrameRect(hdc,&rect,hBrush)

绘制边框,不填充(注意是用画刷,而不是画笔)

InvertRect(hdc,&rect)

像素反转,由1变0,0变1。

(2)操纵RECT结构的函数

操作矩形

函数

1、设置RECT字段

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

2、沿x和y移动几个单位

OffsetRect(&rect,x,y);

3、增大或减小矩形

InflateRect(&rect,x,y);

4、矩形各字段设为0

SetRectEmpty(&rect);

5、复制矩形

CopyRect(&DestRect,&SrcRect);

6、获取矩形的交集

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

7、判断矩形是否为空

bEmpty = IsRectEmpty(&rect);

8、点是否在矩形内部

bInRect = PtInRect(&rect,point);

 

5.6.2 随机矩形

(1)GetMessage与PeekMesssage的区别

 

GetMessage

PeekMessage

作用

获取一条消息,并从消息队列里删掉除该消息(除WM_PAINT外)。

检查消息队列的消息,是否删除,取决于最后一个参数是PM_REMOVE或PM_NOREMOVE。

控制权

获得消息,才返回。

立即返回,不管是否有消息

返回值

获得非WM_QUIT消息时,返回非零

获得WM_QUIT时,返回0

TRUE表示有消息,FALSE表示没有消息。

(2)删除WM_PAINT消息:唯一的方法是使无效区域变成有效。可以用ValidateRect等。

//以下是错误,如果WM_PAINT在队列中,循环将无法退出。

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

(3)消息循环另一法表示法

GetMessage方法

PeekMessage方法

while(GetMessage(&msg,NULL,0,0))

{

     TranslateMessage(&msg);

     DispatchMessage(&msg);

}

return msg.wParam;

While(TRUE)

{   //有消息时正常处理

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

{

    //必须检查WM_QUIT消息

    if(msg.message == WM_QUIT) break;

    TranslateMessage(&msg);

    DispatchMessage(&msg);

}

else //消息队列为空时

{

    //空闲时,做其他事情

}

}

return msg.wParam;

【RandRect程序】
技术分享
/*-----------------------------------------
RANDRECT.C --
(c) Charles Petzold, 1998
-----------------------------------------*/
#include <windows.h>
static int cxClient, cyClient;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawRectangle(HWND hwnd)
{
    HBRUSH hBrush;
    HDC hdc;
    RECT rect;

    //随机矩形rand()返回0-0x7fff之间的整数
    SetRect(&rect, rand() % cxClient, rand() % cyClient, rand() % cxClient, rand() % cyClient);
    //随机颜色
    hBrush = CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256));
    //填充
    hdc = GetDC(hwnd);
    FillRect(hdc, &rect, hBrush);
    ReleaseDC(hwnd, hdc);
    DeleteObject(hBrush);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("RandRect");
    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("RandRect"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    //用PeekMessage的消息循环
    while (TRUE)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT) break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            DrawRectangle(hwnd);
        }
    }

    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

5.6.3 矩形与区域的剪裁

(1)区域可进行绘图或剪裁,是一个GDI对象,得选入设备和DeleteObject。

(2)创建区域

    ①hRgn =CreateRectRgn(xLeft,yTop,xRight,yBottom); //矩形区域

②hRgn =CreateEllispseRgn(xLeft,yTop,xRight,yBottom);//椭圆区域

③hRgn =CreatePolygonRgn(&apt,iCount,iPolyFillMode); //多边形区域

(3)区域的合并iRgnType=CombineRgn(hDestRgn,hSrcRgn1,hSrcRgn2,iCombine)

参数

iCombine值

RGN_AND

两个源区域公共部分

RGN_OR

两个源区域的全部

RGN_XOR

两源区域全部,但去除公共部分

RGN_DIFF

源1不在源2的部分

RGN_COPY

源1全部(忽略源2)

返回值

iRgnType

NULLREGION

空区域

SIMPLEREGION

简单矩形、椭圆或多边形

COMPLEXREGION

复杂区域

ERROR

有错误发生

说明:①将两个源区域组合起来,并产生目标句柄,hDestRgn先前的区域将被销毁。

      ②使用函数前,可让hDestRgn在初始时表示一个很小的矩形区域。

(4)区域绘图函数

FillRgn(hdc,hRgn,hBrush)

//与FillRect类似

FrameRgn(hdc,hRgn,hBrush,xFrame,yFrame)

//xFrame,yFrame表示区域周围的边框的逻辑宽度和高度

InvertRgn(hdc,hRgn);

//与InvertRect类似

PaintRgn(hdc,hRgn);

//用当前设备环境的画刷来填充区域

(5)删除区域:DeleteObject(hRgn); //要删除,因为是GDI对象。

5.6.4 矩形与区域的剪裁

(1)无效矩形和无效区域的产生与获取

无效区产生

获取

//无效矩形

InvalidateRect(hwnd,NULL,TRUE)

//无效区域(形状不一定是矩形)

InvalidateRgn(hwnd,hRgn,TRUE)

BeginPaint(hdc,&ps)或

GetUpdateRect

(2)创建自己的剪裁区域

①SelectObject(hdc,hRgn);

②SelectClipRgn(hdc,hRgn);

(3)删除剪裁区域:GDI为剪裁区域做了一个副本,因此区域选入设备环境后,可以删除。
5.6.5 CLOVER程序

技术分享

/*------------------------------------------------------------

CLOVER.C -- Clover Drawing Program Using Regions
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#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,                  // window class name
        TEXT("三叶虫图形"), // window caption
        WS_OVERLAPPEDWINDOW,        // window style
        CW_USEDEFAULT,              // initial x position
        CW_USEDEFAULT,              // initial y position
        CW_USEDEFAULT,              // initial x size
        CW_USEDEFAULT,              // initial y size
        NULL,                       // parent window handle
        NULL,                       // window menu handle
        hInstance,                  // program instance handle
        NULL);                     // creation parameters

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC          hdc;
    PAINTSTRUCT  ps;
    static int   cxClient, cyClient;
    static HRGN  hRgnClip;
    double       fAngle, fRadius;
    HRGN         hRgnTemp[6];
    switch (message)
    {
    case WM_CREATE:

        return 0;
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        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);    //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 (int i = 0; i < 6; i++)
        {
            DeleteObject(hRgnTemp[i]);
        }
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        //将逻辑点(0,0)映射到客户区中央
        SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL);
        //设置剪裁区域
        SelectClipRgn(hdc, hRgnClip);
        //画射线
        int xPos, yPos;
        fRadius = _hypot(cxClient / 2.0, cyClient / 2.0);//射线长度
        for (fAngle = 0.0; fAngle < TWO_PI; fAngle += TWO_PI / 360)
        {
            MoveToEx(hdc, 0, 0, NULL);
            xPos = (int)(fRadius * cos(fAngle) + 0.5); //加0.5是为了四舍五入取整,如3.5+0.5,取整4。
            yPos = (int)(fRadius * sin(fAngle) + 0.5);
            LineTo(hdc, xPos, yPos);
        }

        EndPaint(hwnd, &ps);
        return 0;

    case WM_DESTROY:
        if (hRgnClip) DeleteObject(hRgnClip);
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

 

 

 

第5章 绘图基础_5.6 矩形、区域和剪裁

标签:

原文地址:http://www.cnblogs.com/5iedu/p/4656167.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!