MFC经典绘图方法总结
- 格式:doc
- 大小:36.00 KB
- 文档页数:8
第一次用MFC编程,边做边google,把学到的东西做一个总结。
其中可能有误解。
还有些部分留出了标题但没写内容――是因为还没用到那些,故尚未研究。
所有讨论仅针对单文档应用程序(SDI)。
第一章,准备:一,继承与虚函数1,子类重载基类成员函数:(1)覆盖式重载:子类的重载函数完全覆盖掉原基类函数的实现。
如MFC中的OnDraw。
(2)追加式重载:子类的重载函数中调用原基类的函数,只是在此之外又加入一些新语句。
如MFC中的OnTimer, OnLButtonDown, OnMouseMove,OnMouseWheel,OnSetCursor。
2,重载的缺陷及虚函数的解决:若子类重载了基类成员函数:当用子类对象加点运算符访问该函数时,调用的是子类函数,无问题。
但当用基类指针访问子类对象的该函数时,调用的却是原基类函数,与预期不符。
为解决此问题,引入虚函数:将基类被子类重载的函数声明为虚函数,再用基类指针访问子类对象的该函数时,调用的就是子类函数了,恢复了合理性。
注:将基类某成员函数声明为虚函数以后,子类中相应的重载函数也就自动成为了虚的(无论是否加virtual修饰),但为了清晰起鉴,最好也加上virtual。
注:抛开内部实现,仅从理解角度讲,可以认为:虚函数=重载+对象类层次识别。
3,纯虚函数与抽象基类没有实现的虚函数称为纯虚函数,含有纯虚函数的类为抽象类。
抽象类不能定义对象,要向下派生出具体类,因此称作抽象基类。
抽象类中的纯虚函数必须在派生类中给予实现。
抽象类的意义在于从更高抽象层次上为各种对象提供统一接口。
二,消息映射:1,控件消息映射:(1)控件消息:最常见的控件消息有两个:MAND消息:只在点击时响应。
2.UPDA TE_COMMAND_UI消息:时时响应。
还有其它的控件消息,如Button控件的BN_CLICKED消息和BN_DOUBLECLICKED消息。
以下仅以COMMAND消息为例。
MFC中的CDC 绘图(2)4.面色(刷)在Windows中,面状图必须用刷(brush)来填充,所以面色是由刷色来确定的。
MFC中的刷类为CBrush(它也是CGDIObject的派生类),刷的创建与使用的步骤与笔的相似。
构造函数有4个:CBrush( ); // 创建一个刷的空对象CBrush( COLORREF crColor ); // 创建颜色为crColor的实心刷CBrush( int nIndex, COLORREF crColor ); // 创建风格由nIndex指定且颜色为crColor的条纹(hatch孵化)刷,其中nIndex可取条纹风格(Hatch Styles)值:符号常量数字常量风格HS_HORIZONTAL 0 水平线HS_VERTICAL 1 垂直线HS_FDIAGONAL 2 正斜线HS_BDIAGONAL 3 反斜线HS_CROSS 4 十字线(正网格)HS_DIAGCROSS 5 斜十字线(斜网格)CBrush( CBitmap* pBitmap ); // 创建位图为pBitmap的图案刷如:pDC->FillRect( &rect, new CBrush( RGB(r, g,b) ) );与构造函数相对应,有多个创建不同类型刷的成员函数:BOOL CreateSolidBrush( COLORREF crColor );BOOL CreateHatchBrush( int nIndex, COLORREF crColor );BOOL CreatePatternBrush( CBitmap* pBitmap );BOOL CreateDIBPatternBrush( HGLOBAL hPackedDIB, UINT nUsage );BOOL CreateDIBPatternBrush( const void* lpPackedDIB, UINT nUsage );BOOL CreateBrushIndirect( const LOGBRUSH* lpLogBrush );BOOL CreateSysColorBrush( int nIndex );预定义的刷对象有BLACK_BRUSH(黑刷)、DKGRAY_BRUSH(暗灰刷)、GRAY_BRUSH(灰刷)、HOLLOW_BRUSH(空刷)、LTGRAY_BRUSH(亮灰刷)、NULL_BRUSH(空刷)、WHITE_BRUSH (白刷)缺省的刷为空刷与笔一样,可以用函数SelectObject或SelectStockObject将自定义的刷或预定义的刷选入DC 中,供绘面状图时使用。
MFC画图程序步骤MFC(Microsoft Foundation Class)是一种用于开辟Windows应用程序的C++类库。
在MFC中,我们可以使用GDI(Graphics Device Interface)来创建和操作图形。
下面是使用MFC创建一个简单的画图程序的步骤。
步骤1:创建一个新的MFC项目首先,打开Visual Studio并选择创建一个新的项目。
在项目类型中,选择Visual C++ -> MFC,然后选择MFC应用程序类型。
输入项目名称并选择保存的位置。
在应用程序类型中,选择“单文档”或者“多文档”视图,具体根据你的需求而定。
点击“确定”按钮创建项目。
步骤2:设计用户界面在MFC应用程序中,用户界面是通过对话框资源来设计的。
在资源视图中,双击IDD_DIALOG(或者其他对话框资源)以打开对话框编辑器。
在对话框编辑器中,你可以添加按钮、文本框、菜单等控件来设计你的用户界面。
在画图程序中,你可以添加一个画布控件来显示绘制的图形。
步骤3:添加绘图功能在MFC中,你可以使用GDI来进行绘图操作。
打开你的对话框类的头文件(例如,CMyDialog.h),添加以下头文件引用:#include <afxwin.h>#include <afxext.h>#include <afxdisp.h>在对话框类的源文件(例如,CMyDialog.cpp)中,添加以下代码来处理绘图操作:```void CMyDialog::OnPaint(){CPaintDC dc(this); // 用于绘制的设备上下文// 在这里进行绘图操作dc.Rectangle(100, 100, 200, 200); // 绘制一个矩形dc.Ellipse(300, 100, 400, 200); // 绘制一个椭圆}```步骤4:处理绘图事件在对话框类的消息映射中添加对绘图事件的处理。
本章学习目标⏹MFC上机操作步骤⏹MFC绘图方法⏹CDC类的主要绘图成员函数⏹设备上下文的调用和释放⏹双缓冲机制⏹MFC 绘制图形的几种方法本章内容2.1 MFC上机操作步骤2.2 MFC绘图方法2.3 设备上下文的调用与释放2.4 双缓冲机制2.5 MFC绘图的几种方法2.6 本章小结2.1 MFC上机操作步骤微软基类库MFC(microsoft foundation class library,MFC)是以C++形式封装的Windows API (Application Program Interface),包含了200多个已经定义好的常用基类。
在程序设计过程中,一般是通过MFC 调用基类的成员函数来完成设计任务的。
1. 从Windows的开始菜单中启动Microsoft Visual C++ 6.0,如图2-1所示。
图2-1 Visual C++启动菜单2. 在Visual C++集成开发环境中,从File|New菜单命令,弹出New对话框,切换到Projects选项卡。
如图2-2所示。
图2-2 New 对话框3. 在MFC AppWizard-Step1对话框中,选中Single Document单选按钮,其余保持默认值,如图2-3所示。
单击Finish按钮。
图2-3 MFC AppWizard-Step1 对话框4. 弹出New Project Information对话框。
如图2-4所示。
单击OK按钮。
图2-4 New Project Information 对话框5. 完成上述步骤后,Test工程的MFC应用程序框架已经生成。
如图2-5所示。
图2-5 应用程序框架6. 在应用程序框架的ClassView标签页中显示所创建的类和成员函数;在ResourceView标签页板中显示所创建的资源;在FileView标签页中显示源程序文件。
如图2-6所示。
图2-6 应用程序框架的三个标签页显示标签页:从ClassView标签页可以看出,CTestApp是应用的主函数类,用来处理消息。
MFC画图的基本方法1.画笔类,CPen,创建画笔类的对象后,需要调用CreatePen(......)函数创建画笔。
然后将其选入设备描述表中。
pDC->SelectObject(.......);2.设置起点坐标。
在这里调用一个函数来设置坐标原点。
pDC->SetViewportOrg(100,255);3.调用LineTo(point),MoveTo(Point)函数画图。
4.删除创建的画笔对象。
pen.DeleteObject();以下是今天所写的画正弦函数的图像。
创建一个单文档的应用程序。
并且在VIEW类中的OnDraw(。
)函数里面做消息响应。
由于调用了sin()函数,所以要把math.h头文件包含进来。
#include "math.h"void CDrawSinXView::OnDraw(CDC* pDC){CDrawSinXDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data here//建立画笔CPen pen_Zuobixi,pen_sinx;pen_Zuobixi.CreatePen(PS_SOLID,4,RGB(0,0,0));pen_sinx.CreatePen(PS_SOLID,2,RGB(0,0,255));pDC->SelectObject(&pen_Zuobixi);//指定原点pDC->SetViewportOrg(100,255);pDC->SetTextColor(RGB(255,0,0));//绘制横坐标CString sPIText[]={"-1/2π","","1/2π","π","3/2π","2π","5/2π","3π","7/2π","4π","9/2π","5π"};int n=-1;int nTemp=0;while (nTemp<=660){pDC->LineTo(60*n,0);pDC->LineTo(60*n,-5);pDC->MoveTo(60*n,0);pDC->TextOut(60*n-sPIText[n+1].GetLength()*3,16,sPIText[n+1]);n++;nTemp +=60;}pDC->MoveTo(0,0);CString strTemp;//绘制纵坐标for(n=-4,nTemp = 0;nTemp<=180;n++,nTemp+=60) {pDC->LineTo(0,60*n);pDC->LineTo(5,60*n);pDC->MoveTo(0,60*n);strTemp.Format("%d",-n);pDC->TextOut(10,60*n,strTemp);}double y,radian;pDC->SelectObject(&pen_sinx);for(int x=-60;x<600;x++){//弧度=X坐标/曲线宽度*角系数*π//Y坐标=振幅*曲线宽度*sin(弧度)radian =x/((double)60*2)*PI;y=sin(radian)*2*60;pDC->MoveTo((int)x,(int)y);pDC->LineTo((int)x,(int)y);}pen_sinx.DeleteObject();。
MFC绘图基础.先认识⼀下MFC中的⼀些和绘图有关的结构体和类1.点(1)点结构POINT点数据结构POINT⽤来表⽰⼀点的x、y坐标:typedef struct tagPOINT {LONG x;LONG y;} POINT;(2)点类CPoint点类CPoint为⼀个没有基类的独⽴类,封装了POINT结构,有成员变量x和y其构造函数有5种:CPoint( );CPoint( int initX, int initY );CPoint( POINT initPt );CPoint( SIZE initSize );CPoint( LPARAM dwPoint );// 低字设为x、⾼字设为yCPoint类还定义了4个平移和设置函数:void Offset(int xOffset, int yOffset);void Offset(POINT point);void Offset(SIZE size);void SetPoint(int X, int Y);CPoint类还重载了+、-、+=、-=、==、!=等运算符来⽀持CPoint对象和CPoint、POINT、SIZE对象之间的运算。
2.⼤⼩(1)⼤⼩结构SIZE⼤⼩(size尺⼨)结构SIZE⽤来表⽰矩形的宽cx和⾼cy:typedef struct tagSIZE {LONG cx;LONG cy;} SIZE(2)⼤⼩类CSize⼤⼩类CSize也为⼀个没有基类的独⽴类,封装了SIZE结构,有成员变量cx和cy其构造函数也有5种:CSize( );CSize( int initCX, int initCY );CSize( SIZE initSize );CSize( POINT initPt );CSize( DWORD dwSize ); // 低字设为cx、⾼字设为cyCSizet类也重载了+、-、+=、-=、==、!=等运算符来⽀持CSize对象和CSize、POINT、SIZE、RECT对象之间的运算3.矩形(1)矩形结构RECT矩形结构RECT定义了矩形的左上⾓与右下⾓的坐标:typedef struct tagRECT {LONG left;LONG top;LONG right;LONG bottom;} RECT;(2)矩形类CRect矩形类CRect也为⼀个没有基类的独⽴类,封装了RECT结构,有成员变量left、top、right和bottom其构造函数有6种:CRect( );CRect( int l, int t, int r, int b );CRect( const RECT& srcRect );CRect( LPCRECT lpSrcRect );CRect( POINT point, SIZE size );CRect( POINT topLeft, POINT bottomRight );CRect类重载了=,+、-,+=、-=,==、!=,&、|,& =、|=等运算符来⽀持CRect对象和CRect、POINT、SIZE、RECT对象之间的运算。
MFC经典绘图方法总结Windows 绘图的实质就是利用windows提供的图形设备接口GDI(Graphics Device Interface)将图形会制在显示器上。
为了支持GDI绘图,MFC提供了两种重要的类:设备上下文DC(Device Context)类,用于设置绘图属性和绘制图形;绘图对象类,封装了各种GDI绘图对象,包括画笔、刷子、字体、位图、调色板和区域。
CDC类介绍:在MFC中,CDC是设备上下文类的基类,派生类包括:CClientDC, CPaintDC, CWindowDC, CMetaFileDC类CClientDC 客户区设备上下文,绘制客户区时CPaintDC 一般发生在窗口需要重绘时CWindwDC 可以绘制整个窗口,通常在窗口WM_NCPAINT消息的响应函数CWnd::OnNCPaint()中使用CMetaFileDC 专门用于图元文件的绘制,图元文件记录一组GDI命令,重建图形输出。
CDC包含m_hDC和m_hAttribDC二个设备上下文。
CDC指导所有对m_hDC的输出GDI调用(SetTextColor)以及对m_hAttribDC的大部分属性GDI调用(GetTextColor)。
CDC对象的重要函数如下:1、为指定设备创建上下文virtual BOOL CreateDC(...)比如创建一个为屏幕的设备上下文CDC dc;dc.CreateDC("DISPLAY", NULL, NULL,NULL);2、创建内存设备上下文,与指定设备上下文兼容virtual BOOL CreateCompatibleDC( CDC * pDC)3、删除CDC对象对应的Windows设备上下文, 通常不调用该函数而是使用析构程序virtual BOOL DeleteDC();4、将HDC句柄转化为设备上下文的句柄: CDC *pDC=CDC::FromHandle( hDC )5、选择GDI对象入选到设备上下文中,一共有五种形式:CPen * SelectObject( CPen * pPen) ;CBrush * SelectObject( CBrush * pBrush) ;virtual CFont * SelectObject( CFont * pFont) ;CBitmap * SelectObject( CBitmap * pBitmap) ;int SelectObject( CRgn * pRgn) ;例:Cpen cpen;pen.CreatePen( PS_SOLID, 2, RGB(255,0,0) );Cpen *pOldPen=(CPen*)pDC->SelectObject(&pen); //设置新画笔,记录旧画笔....pDC->SelectObject(pOldPen); //还原画笔三种方法创建画笔1/构造函数:CPen();CPen( int nPenStyle, int nWidth, COLORREF crColor );CPen(...)略2/CreatePen( int nPenStyle, int nWidth, COLORREF crColor )3/CreatePenIndirect( LPLOGPEN lpLogpen )typedef struct tagLOGPEN{UINT lopnStyle;POINT lopnWidth;COLORREF lopnColor;}LOGPEN, *LPLOGPEN;例:LOGPEN lppn;lppn.lopnColor=RGB(255,0,0);lppn.lopnStype=PS_DASHDOT;lgpn.lopnWidth.x=2;lgpn.lopnWidth.y=2;CPen pen;pen.CreatePenIndirect( &lppn );画刷三种方法创建1/构造函数:CBrush();CBrush(COLROREF crColor);CBrush(int nIndex, COLORREF crColor);nIndex 哪种类型的网格, HS_BDIAGONAL HS_CROSSHS_VERTICAL HS_HORIZONTAL2/CreateSolidBrush( COLORREF crColor);3/CreateHatchBrush( int nIndex , COLORREF crColor );4/CreateBrushIndirect( const LOGBRUSH* lpLogBrush );typedef struct tagBRUSH{UINT lbStyle; // BS_HA TCHED, BS_SOLID , BS_NULLCOLORREF lopnColor;LONG lbHatch; //HS_BDIAGONAL HS_CROSS HS_VERTICAL HS_HORIZONTAL}LOGBRUSH, *LPLOGBURSH;例:CRect Rect(0,0,200,200);CBrush brush(HS_HORIZONTAL,RGB(0,255,0));CBrush *pOldBursh=pDC->SelectObject(&brush);pDC->Rectangle(Rect);pDC->SelectObject( pOldBursh);图形绘制1.点绘制//返回RGB值COLORREF SetPixel(int x, int y, COLORREF crColor);COLORREF SetPixel(POINT point, COLORREF crColor);//返回BOOL值,绘制是否成功.BOOL SetPixelV(int x, int y, COLORREF crColor);BOOL SetPixelV(POINT point, COLORREF crColor);2.直线绘制//返回CPoint对象的x和y坐标的前一次取值CPoint MoveTo(int x, int y);CPoint MoveTo(POINT point);//返回绘制是否成功BOOL MoveTo(int x, int y);BOOL MoveTo(POINT point);例:CPen pen;pen.CreatePen(PS_SOLID,2,RGB(0,255,0));CPen* oldPen =(CPen *)pDC->SelectObject(&pen);CPoint oldPoint=pDC->MoveTo(600,300);pDC->LineTo(500,500);3.矩形绘制1/矩形绘制BOOL Rectangle( int x1, int y1, int x2, int y2 );BOOL Rectangle( LPRECT lpRect);例:pDC->SelectObject( oldPen);pDC->Rectangle(0,0,600,300);CRect Rect(0,0,300,200);CBrush brush(HS_HORIZONTAL,RGB(0,255,0));CBrush *pOldBursh=pDC->SelectObject(&brush);pDC->Rectangle( &Rect );pDC->SelectObject( pOldBursh);例:CPen pen;pen.CreatePen(PS_DASH, 1,RGB(255,0,0));LOGBRUSH lb;memset( &lb,0, sizeof(lb));lb.lbStyle=BS_HATCHED;lb.lbHatch=HS_DIAGCROSS;CBrush brush;brush.CreateBrushIndirect( &lb);CPen *pOldPen=(CPen *)pDC->SelectObject( & pen);CBrush *pOldBrush=(CBrush*)pDC->SelectObject(&brush);pDC->Rectangle(0,0,200,200);pDC->SelectObject( pOldPen);pDC->SelectObject( pOldBrush);2/三维矩形线框绘制void Draw3dRect(int x, int y, int cx, int cy , COLORREF clrTopLeft, COLORBEF clrBottomRight );void Draw3dRect(LPCRECT lpRect, COLORREF clrTopLeft, COLORBEF clrBottomRight );例:pDC->Draw3dRect(100, 100, 200, 300, RGB(255,0,0), RGB(0,255,0));3/表示焦点风格矩形void DrawFocusRect( LPCRECT lpRect);例:CRect rt( 400,400, 450, 450);pDC->DrawFocusRect( &rt);4/绘制拖曳形线框void DrawDragRect(LPCRECT lpRect , SIZE size LPCRECT lpRectLast, SIZE sizeLast, CBrush* pBrush=NULL , CBrush* pBrushLast=NULL);5/圆角矩形void RoundRect(LPCRECT lpRect , POINT point); //point.x 椭圆宽, point.y 椭圆高void RoundRect(int x1, int y1, int x2, int y2, int x3, int y3 );例:pDC->RoundRect(250, 250, 400, 400, 50, 100);4.椭圆绘制BOOL Ellipse( LPCRECT lpRect ) //椭圆的外接矩形范围文字绘制TextOut函数返回值是BOOLBOOL TextOut( int x, int y, const CString & str );virtual BOOL TextOut(int x, int y, LPCSTR lpszString, int nCount);DrawText函数返回值是文本高度int DrawText ( LPCSTR lpszString, int nCount, LPRECT lpRect, UNIT nFormat);int DrawText ( const CString& str, LPRECT lpRect, UNIT nFormat); //DT_BOTTOM DT_LEFT...//注意:如果nFormat 参数指定了DT_CALCRECT标志,由lpRect指定的矩形将会更新,以反映显示文本需要的高度和宽度,但并不绘制显示文字背景色和前景色virtual COLORREF SetBKColor( COLORREF crColor);int SetBKMode( int nBKMode); // nBKMode: OPAQUE, TRANSPARENT时,SetBKColor失效例:CRect rect;GetClientRect(&rect);pDC->FillSolidRect(rect,RGB(0,0,255));CString strText=L"VC++ BKColor Demo...";pDC->SetTextColor(RGB(255,255,255));pDC->SetBkColor(RGB(255,0,0));pDC->SetBkMode(TRANSPARENT);pDC->TextOut(10,10,strText);文字字体设置文字的字体会使用到MFC下的CFont类,然后调用CFont类下的四个成员函数: CreateFont, CreateFontIndirect, CreatePointFont和CreatePointFontIndirect,详见msdn帮助例:1/CreateFont 函数CFont font;font.CreateFont(25,0,1800,0,FW_BOLD,1,1,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH|FF_MODERN,L"Courier New");CString strText=L"VC++ Font Demo...";pDC->SetTextColor( RGB(255,0,0));CFont *pOldFont=(CFont*)pDC->SelectObject(&font);pDC->TextOut(210,210, strText);pDC->SelectObject(pOldFont);2/ CreateFontIndirect(const LOGFONT* lpLogFont);typedef struct tagLOGFONT{//14个成员变量与世隔绝CreateFont函数类似}LOGFONT;3/如果只注重字体的高度和字体名时,使用CreatePointFont(int nPointSize, LPCSTR lpszFaceName, CDC* pDC=NULL);位图显示A:位图介绍,CBitmap类封装了Windows图形设备接口中的位图,并提供了操作位图的成员函数1/创建兼容位图,使之与指定设备兼容.BOOL CreateCompatibleBitmap(CDC *pDC, int nWidth, int nHeight);2/得到位图信息,作用是填充BITMAP结构.int GetBitmap(BITMAP * pBitMap);3/加载位图资源,加载一个命名的位图资源来初始化位图对象.BOOL LoadBitmap( LPCSTR lpszResourceName);BOOL LoadBitmap( UINT nIDResuource );B:显示位图,VC++提供BitBlt, StretchBlt和TransparentBit(需加入msimg32.lib库) 1/ BOOL BitBlt(int x , int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop );//尺寸不变2/ BOOL StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC,int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop); //支持缩放/* dwRop一般设置为SRCCOPY */3/ BOOL TransparentBlt( HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,HDC hdcSrc, int nXoriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc, UINT crTransparent);例:CBitmap bitmap;bitmap.LoadBitmap(IDB_BITAMBOW);BITMAP bm;bitmap.GetBitmap(&bm);CDC MemDC;MemDC.CreateCompatibleDC(pDC);CBitmap* pOldBitmap=(CBitmap *)MemDC.SelectObject(&bitmap);CRect rect(10,10, bm.bmWidth, bm.bmHeight);TransparentBlt(pDC->GetSafeHdc(), rect.left, rect.top, rect.Width()*5, rect.Height()*5, MemDC.GetSafeHdc(), 0, 0, bm.bmWidth, bm.bmHeight, RGB(0,0,0));//长宽扩大5倍,图片中黑色的部分将作为透明处理。