专题:图形绘制

来源:互联网 发布:统计报表数据库设计 编辑:程序博客网 时间:2024/05/29 09:43

      专题二:图形绘制

 提纲:

属性方面的设置(添加)

画图

位图,文件操作的简单介绍

CRgn类的介绍

Normalize()函数

鼠标的捕获

具体内容:

一、          属性方面的设置:

1.       添加画笔和画刷 //实现对图形属性的设置

1)在View类当中添加画笔和画刷颜色的变量,并在构造函数中初始化

View.h中:

COLORREF m_penColor; //绘制颜色

     COLORREF m_brushColor; //画刷颜色

     View.cpp中:

m_penColor=RGB(0,0,0);

    m_brushColor=RGB(255,255,255);

              

 

(2)添加按钮和消息响应函数

void CVectorView::OnPenColor() //设置画笔颜色

void CVectorView::OnBrushColor() //设置画刷颜色

 

2.       在画布上显示选中图形的属性

OnDraw()中添加代码,显示属性:

    //----------显示图形属性----------

    pDC->TextOut(10,10,"画笔颜色");

    pDC->TextOut(10,30,"画刷颜色");

 

    CBrush brush1,brush2,*pOldBrush1,*pOldBrush2;

    brush1.CreateSolidBrush(m_penColor);

    brush2.CreateSolidBrush(m_brushColor);

   

    pOldBrush1=pDC->SelectObject(&brush1);

    pDC->Rectangle(80,15,100,25); 

 

    pDC->SelectObject(pOldBrush1);

   

    pOldBrush2=pDC->SelectObject(&brush2);

    pDC->Rectangle(80,30,100,45);

 

pDC->SelectObject(pOldBrush2);

3.       保证选中图形的属性实时的显示出来

 

SetSelected()中添加代码:

m_penColor=pItem->m_colorLine;

m_brushColor=pItem->m_colorFill;   

 

4.       与属性设置对话框相协调

(1)  首先保证属性对话框要与选中图形的属性信息保持一致

void CVectorView::OnViewProperty()中添加代码如下:

CItem *pItem;

CVectorDoc* pDoc = GetDocument();

        ASSERT_VALID(pDoc);

        for (int i=0; i<pDoc->m_objItem.GetCount(); i++)

        {

            pItem=(CItem*)(pDoc->m_objItem.GetAt(i));

            if (pItem->m_bSelected)

            {

                 GetSelectedItemsInfo();

            }

}  

(2)  协调属性显示和属性设置对话框

void CVectorView::SetSelectedItemsInfo(int property) 中添加代码如下:

m_penColor= m_pDlgProperty->m_colorLine;

m_brushColor = m_pDlgProperty->m_colorFill;

二、          画图

1.       添加图形按钮及消息响应:

(1)椭圆

(2)圆角矩形

(3)五边形

(4)六边形

(5)八边形

(6)多个多边形

(7)Bezier曲线

(8)弧线

(9)位图导入按钮及菜单

2.       画图原理:

总的来说就是在屏幕中选好各个控制点的信息,然后代入画图函数当中即可

 

3.       绘制函数的说明:

(1)    椭圆

        BOOL Ellipse(   int x1,   int y1,   int x2,   int y2 );
        BOOL Ellipse(   LPCRECT lpRect );

pDC->Ellipse(m_ptP1.x,m_ptP1.y,m_ptP2.x,m_ptP2.y);

(2)    圆角矩形

        BOOL RoundRect(   int x1,   int y1,   int x2,   int y2,   int x3,   int y3 );
        BOOL RoundRect(   LPCRECT lpRect,   POINT point );

   pDC->RoundRect(m_ptP1.x,m_ptP1.y,m_ptP2.x,m_ptP2.y,50,50);

(3)    五边形

        BOOL Polygon(   LPPOINT lpPoints,   int nCount );

算法:

void CItem::DrawFivePolygn(CDC *pDC)

{

            percentY=(1-sin(0.1*PI))/(1+sin(0.3*PI));

            percentX1=0.5-1 / (4 * cos(0.2 * PI));

            percentX2=0.5+1 / (4 * cos(0.2 * PI));

 

    pt_Five[0].x=(m_ptP2.x - m_ptP1.x)/2.0 + m_ptP1.x;

pt_Five[0].y=m_ptP1.y;

 

pt_Five[1].x=m_ptP1.x;

pt_Five[1].y=(m_ptP2.y - m_ptP1.y) * percentY + m_ptP1.y;

pt_Five[2].x=(m_ptP2.x - m_ptP1.x) * percentX1 + m_ptP1.x;

pt_Five[2].y=m_ptP2.y;

pt_Five[3].x=(m_ptP2.x - m_ptP1.x) * percentX2 + m_ptP1.x;

pt_Five[3].y=m_ptP2.y;

pt_Five[4].x=m_ptP2.x;

pt_Five[4].y=(m_ptP2.y - m_ptP1.y) * percentY + m_ptP1.y;

 

pDC->Polygon(pt_Five,5);

}

(4)    六边形

        BOOL Polygon(   LPPOINT lpPoints,   int nCount );

算法:

void CItem::DrawSixPolygn(CDC *pDC)//画六边形

{

pt_Six[0].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/2.0;

pt_Six[0].y=m_ptP1.y;

 

pt_Six[1].x=m_ptP1.x;

pt_Six[1].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/4.0;

 

pt_Six[2].x=m_ptP1.x;

pt_Six[2].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)*3/4.0;

 

pt_Six[3].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/2.0;

pt_Six[3].y=m_ptP2.y;

 

pt_Six[4].x=m_ptP2.x;

pt_Six[4].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)*3/4.0;

 

pt_Six[5].x=m_ptP2.x;

pt_Six[5].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/4.0;

 

pDC->Polygon(pt_Six,6);

}

(5)八边形

        BOOL Polygon(   LPPOINT lpPoints,   int nCount );

算法:

 

void CItem::DrawEightPolygn(CDC *pDC)

{

    pt_Eight[0].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/3.0;

    pt_Eight[0].y=m_ptP1.y;

    pt_Eight[1].x=m_ptP1.x;

pt_Eight[1].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/3.0;

 

pt_Eight[2].x=m_ptP1.x;

pt_Eight[2].y=m_ptP1.y+2*(m_ptP2.y-m_ptP1.y)/3.0;

 

pt_Eight[3].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/3.0;

pt_Eight[3].y=m_ptP2.y;

 

pt_Eight[4].x=m_ptP1.x+2*(m_ptP2.x-m_ptP1.x)/3.0;

pt_Eight[4].y=m_ptP2.y;

 

    pt_Eight[5].x=m_ptP2.x;

pt_Eight[5].y=m_ptP1.y+2*(m_ptP2.y-m_ptP1.y)/3;

 

pt_Eight[6].x=m_ptP2.x;

pt_Eight[6].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/3;

 

    pt_Eight[7].x=m_ptP1.x+2*(m_ptP2.x-m_ptP1.x)/3;

    pt_Eight[7].y=m_ptP1.y;

 

    pDC->Polygon(pt_Eight,8);

}

 (6)多个多边形

        BOOL PolyPolygon(   LPPOINT lpPoints,   LPINT lpPolyCounts,   int nCount );

void CItem::DrawAnyPolygn(CDC *pDC)//画多个多边形

{

pt_Eight[0].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/3.0;

pt_Eight[0].y=m_ptP1.y;

 

pt_Eight[1].x=m_ptP1.x;

pt_Eight[1].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/3.0;

 

pt_Eight[2].x=m_ptP1.x;

pt_Eight[2].y=m_ptP1.y+2*(m_ptP2.y-m_ptP1.y)/3.0;

 

pt_Eight[3].x=m_ptP1.x+(m_ptP2.x-m_ptP1.x)/3.0;

pt_Eight[3].y=m_ptP2.y;

 

pt_Eight[4].x=m_ptP1.x+2*(m_ptP2.x-m_ptP1.x)/3.0;

pt_Eight[4].y=m_ptP2.y;

 

pt_Eight[5].x=m_ptP2.x;

pt_Eight[5].y=m_ptP1.y+2*(m_ptP2.y-m_ptP1.y)/3;

 

pt_Eight[6].x=m_ptP2.x;

pt_Eight[6].y=m_ptP1.y+(m_ptP2.y-m_ptP1.y)/3;

 

pt_Eight[7].x=m_ptP1.x+2*(m_ptP2.x-m_ptP1.x)/3;

pt_Eight[7].y=m_ptP1.y;

int arr[2];

arr[0]=5;

arr[1]=3;

   

pDC->PolyPolygon(pt_Eight,arr,2);

}

         (7)Bezier曲线
        BOOL PolyBezier(   const POINT* lpPoints,   int nCount );

pDC->PolyBezier(m_ptP,4);

注:该部分还涉及到控制点的录入,实现方法:

    设置控制点个数pointcount=0,在鼠标按下函数中判断pointcount是否小于4(暂时用四个点)并绘制控制点,然后当pointcount=4时完成控制点绘制,将m_bDrawing设为true,在鼠标弹起时形成图形对象,把它加入到对象数组当中即可。

(8)弧线

BOOL Arc(   int x1,   int y1,   int x2,   int y2,   int x3,   int y3,   int x4,   int  y4);     
   BOOL Arc(   LPCRECT lpRect,   POINT ptStart,   POINT ptEnd );

pDC->Arc(CRect(m_ptP1,m_ptP2),m_ptArc[2],m_ptArc[3]);

 

弧线的坐标定位

注:这里也涉及控制点的问题,处理方法与上面完全相同。

9)饼图:(在程序当中没有实现)
BOOL Pie(   int x1,   int y1,   int x2,   int y2,   int x3,   int y3,   int x4,   int y4 );
BOOL Pie(   LPCRECT lpRect,   POINT ptStart,   POINT ptEnd );

(10)位图导入按钮及菜单

  //下面再讲

 

三、          位图,文件的操作介绍

void CVectorView::OnFileLoadimage()

{

 

    if(m_nType == ITEM_BITMAP)

    {

        m_nType = ITEM_EMPTY;

    }

    else

    {

        m_nType = ITEM_BITMAP;

    }

 

    CFileDialog pCFileDialog(true, NULL, NULL, 0, "位图文件(*.bmp)|*.bmp");

    pCFileDialog.m_ofn.lpstrTitle = "打开文件";

 

    if(pCFileDialog.DoModal() != IDOK)

    {

    return;

    }

    strfilepath=pCFileDialog.GetPathName();//获取文件路径与名称

    //获取文件名

    CString filename;

    filename=pCFileDialog.GetFileName();

 

    //获取exe文件自身所在文件夹

    CString dir;

    char filepath[255];

    GetModuleFileName(AfxGetInstanceHandle(),filepath,256);

    //得到play.exe的路径和文件名

    int hf=0;

    dir=filepath;

    while(dir.Find("//",hf)!=-1)

    {

        hf=dir.Find("//",hf);

        hf=hf+1;

    }

    int w=dir.GetLength();

    dir.Delete(hf,w-hf);

 

    dir=dir+"res//";

 

 

  //导入文件

    CString StrSourceFile=strfilepath;

    CString StrDestFolder=dir;

    char SourceFile[255+1]="";  //此处必须为字符数组,CString类型是不行的

    strcpy(SourceFile,StrSourceFile); //此种方法非常之好

    char TargetFolder[255+1]="";

    strcpy(TargetFolder,StrDestFolder);

    SHFILEOPSTRUCT lpFile;

    lpFile.hwnd=GetSafeHwnd();

    lpFile.wFunc=FO_COPY;

    lpFile.pFrom=SourceFile;

    lpFile.pTo=TargetFolder;

    lpFile.fFlags=FOF_ALLOWUNDO;

    lpFile.fAnyOperationsAborted=FALSE;

    lpFile.hNameMappings=NULL;

    lpFile.lpszProgressTitle=NULL;

    int ReturnValue=SHFileOperation(&lpFile);

 

    if(ReturnValue==0)

    {

        if(lpFile.fAnyOperationsAborted==TRUE)

            MessageBox("导入文件的操作被取消","信息提示",MB_OK+MB_ICONWARNING); //这里导入实际上就是复制,把文件复制到res文件夹当中

        else

        {

            MessageBox("导入文件操作成功","信息提示",MB_OK+MB_ICONWARNING);

            m_nType=ITEM_BITMAP;

 

            //新建立一个图形pItem

   

            CItem *pItem;

            pItem=new CItem;

            pItem->m_nType=m_nType;

            pItem->m_ptP1=CPoint(100,100);

            pItem->m_ptP2=CPoint(165,155);

            pItem->m_bitmapName=dir+filename;

           

            pItem->m_bSelected=true;

            AfxMessageBox(pItem->m_bitmapName);

            //pItem加入m_objItem

            CVectorDoc* pDoc = GetDocument();

            ASSERT_VALID(pDoc);

            if (!pDoc)

                return;

            pDoc->m_objItem.Add(pItem);

            //通知pDoc文件内容已经发生改变

            pDoc->SetModifiedFlag(true);

 

            DrawAll();

            Invalidate(0);

            m_nType=ITEM_EMPTY;//一定要注意这里

        }

    }

    else

        MessageBox("导入文件操作失败","信息提示",MB_OK+MB_ICONEXCLAMATION);

}

 

void CItem::DrawBitMap(CDC *pDC) //绘制位图

{

    BITMAP bmp;

    HBITMAP hBitmap;   

    CBitmap m_Bitmap;

    CDC dcCompatible;

 

    hBitmap=(HBITMAP)LoadImage(AfxGetInstanceHandle(),

            m_bitmapName,

            IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);

 

        if (hBitmap == NULL)

        {      

            MessageBox(NULL,"Can't find the picture!","ERROR",MB_OK);

            exit(0);//退出程序

        }

 

    m_Bitmap.Attach(hBitmap);

    m_Bitmap.GetBitmap(&bmp);

 

    dcCompatible.CreateCompatibleDC(pDC);

    dcCompatible.SelectObject(&m_Bitmap);

 

    pDC->StretchBlt(m_ptP1.x,m_ptP1.y,m_ptP2.x-m_ptP1.x,m_ptP2.y-m_ptP1.y,& dcCompatible,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);

 

    dcCompatible.DeleteDC();

 

}

四、          CRgn类的介绍

区域CRgn类:封装GDI区域。区域是窗口内的一块多边形或椭圆形的区域。CRgn用于设备环境(通常是窗口)内的区域操作。CRgn通常与CDC的有关剪裁(clipping)的成员函数配合使用。

代码示例:

CRgn rgn;

    rgn.CreatePolygonRgn(pt_Five,5,ALTERNATE);// nMode是填充模式,可为ALTERNATEWINDING.

rgn.PtInRegion(point)

五、          Normalize()函数

void CItem::Normalize()//八边形的规则化,仿造矩形的Normalize()函数,保证改变大小是箭头等其他元素的正确性

                        //AtKeyPoint()中调用

{

    CPoint pt_temp;

    if(pt_Eight[0].y>pt_Eight[3].y)

    {

        pt_temp=pt_Eight[0];

        pt_Eight[0]=pt_Eight[3];

        pt_Eight[3]=pt_temp;

 

        pt_temp=pt_Eight[7];

        pt_Eight[7]=pt_Eight[4];

        pt_Eight[4]=pt_temp;

 

        pt_temp=pt_Eight[1];

        pt_Eight[1]=pt_Eight[2];

        pt_Eight[2]=pt_temp;

 

        pt_temp=pt_Eight[6];

        pt_Eight[6]=pt_Eight[5];

        pt_Eight[5]=pt_temp;

    }

    else if(pt_Eight[0].x>pt_Eight[7].x)

    {

        pt_temp=pt_Eight[0];

        pt_Eight[0]=pt_Eight[7];

        pt_Eight[7]=pt_temp;

 

        pt_temp=pt_Eight[1];

        pt_Eight[1]=pt_Eight[6];

        pt_Eight[6]=pt_temp;

 

        pt_temp=pt_Eight[2];

        pt_Eight[2]=pt_Eight[5];

        pt_Eight[5]=pt_temp;

 

        pt_temp=pt_Eight[3];

        pt_Eight[3]=pt_Eight[4];

        pt_Eight[4]=pt_temp;

    }

}

六、          鼠标的捕获

// void CVectorView::OnLButtonDown(UINT nFlags, CPoint point)

    SetCapture();

//void CVectorView::OnLButtonUp(UINT nFlags, CPoint point)

ReleaseCapture();

 

 

 

原创粉丝点击