计算机图形学实验 用VC++在屏幕上绘图
如何建立一个VC++应用程序框架文件:
一.MFC绘图函数: 1.1 生成设备环境对象 设备环境是一个对窗口的绘图表面的属性保持跟踪的数据结构。这些属性包括用于在屏幕上绘图的当前所使用的画笔和画刷。与可以同时使用很多画刷和画笔的艺术家不同,设备环境每次只能用一种画笔和一种画刷。而设备环境对象就是设备环境类的一个实例,它设置了绘图工具,并提供了绘制点,线等简单图形的绘图函数。所有的绘图工作都要通过设备环境对象来实现。
例如,如果想用一个能够画粗线条的画笔,就必须创建一个新画笔,然后用它取代设备环境中原有的画笔。类似的,如果想用红色的画刷填充一个图形,必须创建一个画刷,并将它选进设备环境,这就是Windows程序员在设备环境中取代工具的方式。
下面简单介绍几种设备环境: ①.CDC 设备环境对象类,是其它设备环境的基类。 一般情况下,应用程序都要在View(视图)类中来进行绘图,视图窗口绘制或者重绘,应用程序框架都要调用视图类的OnDraw成员函数。 void CMyDrawView::OnDraw(CDC* pDC) { // TODO: add draw code for native data here }
②.CPaintDC 构造函数调用BeginPaint ,析构函数调用EndPaint。 有时在视图窗口以外的窗口(如对话框)中绘制图形,需要调用窗口类的WM_PAINT的消息处理函数 OnPaint来绘制或者重绘窗口,OnPaint函数必须生成由 CPaintDC类派生的设备环境对象,如下所示: void CMyDialog::OnPaint() { CPaintDC dc(this); } (*)
CPaintDC dc(this);创建一个名为dc的设备环境对象,而this指向当前的对话框。这样就可以在对话框画图了。 注意:由于视图类窗口也是窗口的一类,所以视图窗口要绘制时也收到WM_PAINT 的消息,但是Cview提供一个OnPaint函数,生成和准备设备环境对象,然后将对象传入OnDraw函数。只有不从视图类派生的窗口类才需要提供自己的OnPaint函数做各种窗口绘图工作。
③.CClientDC 这个设备环境对象仅仅代表了当前窗口区域。它的构造函数调用GetDC函数,它的析构函数调用ReleaseDC 函数。 对于在OnDraw和OnPaint处理器之外的函数中显示图形,必须生成CClientDC类成员的设备环境对象。 CMyFunction::Function() {CClientDC ClientDC(this); // TODO: Add your message handler code here}
1.2 选择绘图工具 画笔,画刷,字体等等。 系统默认的画笔和画刷: 默认的画笔画出的线为宽度为1像素的黑色实线。默认的画刷是白色的,己用默认的画刷填充图形时,图形的内部填充成白色。
1.2.1 选用库存的绘图工具 CDC::SelectStockObject(int nIndex); void CMyView::OnDraw(CDC*pDC) { pDC-> SelectStockObject(WHITE_PEN); SelectStockObject(GRAY_BRUSH); }
1.2.2 生成自定义的绘图工具 生成自定义画笔和画刷的基本步骤: (1)生成画笔(CPen类)和画刷(CBrush)类的实例; (3)将生成的画笔和画刷选入设备环境对象中,并将设备环境对象的原有的画笔和画刷保存在指针中; (4)调用相应的绘图函数进行绘图; (5)将原来的画笔和画刷重新选入设备环境对象中
(1)生成笔(CPen类)和刷(CBrush)类的实例; CPen pen; CBrush brush; (2)调用CPen类和CBrush类的成员函数来初始化笔和刷; 画笔的初始化 CPen::CreatePen
BOOL CreatePen(int nPenStyle, int nWidth,COLORREF crColor); nPenStyle : PS_SOLID PS_DOT PS_DASH PS_DASHDOT PS_DASHDOTDOT nWidth : 线的宽度(线宽>1均产生实线)
COLORREF RGB(BYTE bRed , BYTE bGreen, BYTE bBlue); crColor参数指定线的颜色,类型为 COLORREF RGB(BYTE bRed , BYTE bGreen, BYTE bBlue); 0≤bRed ,bGreen, bBlue≤255 RGB宏功能定义了16种纯颜色。
RGB(0,0,0);黑色RGB(255,255,255);白色 RGB(128,0,0);深红RGB(255,0,0);淡红 RGB(0, 128,0);深绿RGB(0, 255,0);淡绿 RGB(0,0,128);深蓝RGB(0,0.255);淡蓝 RGB(128,128,0);深黄 RGB(255,255,0);淡黄 RGB(0,128,128);深青 RGB(0,255,255);淡青 等。
画刷的初始化: BOOL CreateSolidBrush( COLORREF crColor); BOOL CreateHatchBrush( int nIndex,COLORREF crColor); BOOL CreatePatternBrush( Cbitmap *pBitmap);
nIndex指定格子的形式。 HS_CROSS 水平垂直交叉阴影 HS_HORIZONAL 水平阴影线 HS_VERTICAL 竖直阴影线 HS_DIAGCROSS 45度交叉阴影对角线 HS_BDIAGONL 以45度角从左上到右下倾斜的阴影 HS_FDIAGONL 以45度角从左下到右上倾斜的阴影
(3)将生成的笔和刷选入设备环境对象中,并将设备环境对象的原有的笔和刷保存在指针中; CDC::SelectObject CPen * SelectObject (CPen *pPen); CBrush*SelectObject(Cbrush*pBrush); 注意:该函数返回的是原来的设备环境对象的指针
1.3 设置绘图属性 (1) 背景色 GetBkColor()返回当前的背景色。 SetBkColor(COLORREF crColor)函数是将当前的背景色设置成参数crColor所代表的颜色值。
(2)背景方式 GetBkMode() SetBkMode(int nBkMode) nBkMode: OPAQUE TRANSPARENT 这两个函数主要影响Chord ,Ellipse和Pie等闭合图形绘图函数。
(3)绘图方式 GetROP2( ); int SetROP2( int nDrawMode ); 绘图方式(nDrawMode) 组合后像素的颜色 R2_BLACK 总为黑色 R2_WHITE 总为白色 R2_NOT 颜色与屏幕颜色相反 R2_COPYPEN 具有画笔的颜色 R2_NOTCOPYPEN 具有与画笔相反的颜色
1.4 几种常用的绘图函数 1.画线函数 (1) 成员函数MoveTo:将当前的绘图位置移到point 指定的坐标处 1.4 几种常用的绘图函数 1.画线函数 (1) 成员函数MoveTo:将当前的绘图位置移到point 指定的坐标处 CPoint MoveTo(int x,int y); CPoint MoveTo(POINT point); (2) 成员函数LineTo 在当前的绘图位置上与一个新坐标点之间画一条直线,这个新的坐标点将变成当前位置。 BOOL LineTo (int x,int y); BOOL LineTo (POINT);
(3)成员函数Arc 画一个椭圆形的弧线,它是一个指定边界矩形内一个内切椭圆的一段。 BOOL Arc(int x1,int y1,int x2, int y2,int x3,int y3,int x4,int y4); (4)成员函数PolylBezier BOOL PolyBezier( const POINT *lpPoints,int nCount); 绘制由几个控制点所决定的多条Bezier曲线 一般给定的点为所画样条函数的3倍加1
void CMyDrawView::OnDraw(CDC *pDC) { CPen Pen; CPen *OldPen; Pen.CreatePen(PS_SOLID,4,RGB(0,0,0)); OldPen=pDC->SelectObject(&Pen); POINT points[7];
points[0].x=100; points[0].y=100; pDC->PolyBezier(points,7); pDC-> SelectObject(OldPen);}
2.画简单的闭合图形 BOOL Rectangle(int x1,int y1, int x2,int y2); (2) Ellipse BOOL Ellipse(int x1,int y1,
(3) Chord(一个椭圆和一条直线相交的图形) BOOL Chord(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4); (4) Polygon BOOL Polygon( LPPOINT lpPoints, int nCount ); LpPoints是一个指向CPoint实例的POINT数组的指针 其中 nCount>2
void CMyTestView::OnDraw(CDC *pDC) {CPen Pen; CPen *OldPen; CBrush Brush;CBrush *OldBrush; Pen.CreatePen(PS_SOLID,5,RGB(0,0,0)); Brush.CreateSolidBrush(RGB(0,255,0)); OldPen=pDC->SelectObject(&Pen); OldBrush=pDC->SelectObject(&Brush); pDC->Chord(120,20,420,450,100,0,400,200); pDC->SelectObject(OldPen); pDC->SelectObject(OldBrush);}
二..实例 void CMyTestView::OnDraw(CDC *pDC) {CPen Pen;CPen *OldPen; Pen.CreatePen(PS_SOLID,2,RGB(255,255,0)); CBrush Brush; CBrush *OldBrush; Brush.CreateHatchBrush(4,RGB(0,200,200)); OldPen= pDC->SelectObject(&Pen); OldBrush=pDC->SelectObject(&Brush);
pDC->RoundRect(100,100,300,300,30,60); pDC->SetBkColor(RGB(255,255,0)); pDC->SetBkMode(OPAQUE); pDC->Ellipse(300,100,500,200); pDC->Pie(300,100,600,400,300,400,600,400); pDC->SelectObject(OldPen); pDC->SelectObject(OldBrush); }
三.鼠标消息函数的应用:
void CMyLineView::OnLButtonDown (UINT nFlags, CPoint point) { m_Oldpoint=point;//保存光标的当前位置 m_Newpoint=point;//存放画线的起始位置 SetCapture(); //捕捉鼠标 m_pLMouseDown=TRUE;//表示鼠标为按下的状态 CRect rect; GetClientRect(&rect);//获得并保存用户区坐标
ClientToScreen(&rect); //用用户区坐标重新计算屏幕坐标 ClipCursor(&rect); //限制光标在用户区内 //默认处理,调用基类消息处理函数 CView::OnLButtonDown(nFlags, point); }
void CMyLineView::OnMouseMove (UINT nFlags, CPoint point) { SetCursor(m_HCursor); //设置自定义光标 if(m_pLMouseDown) {CClientDC dc(this); dc.SetROP2(R2_NOT); //设置绘图模式,以屏幕颜色的相反色绘图
//以重绘的方式擦除前一个OnMouseMove绘制的直线 dc.MoveTo(m_Newpoint); dc.LineTo(m_Oldpoint); dc.MoveTo(m_Newpoint); //重新位置到当前位置画一条直线 dc.LineTo(point); m_Oldpoint=point; //存放当前鼠标位置 } CView::OnMouseMove(nFlags, point);}
void CMyLineView::OnLButtonUp (UINT nFlags, CPoint point) {if(m_pLMouseDown) { m_pLMouseDown=FALSE;//标志鼠标释放 ReleaseCapture();//释放鼠标捕捉 ClipCursor(NULL);//使光标可以随意移动} CView::OnLButtonUp(nFlags, point);}