mfc绘图 结构与函数大全

mfc绘图(转载)

1 几何对象的结构和类
为了使用绘图函数,应该先了解绘图所用到的几种表示几何对象的结构和类。这些结构和类分别定义在头文件windef.h和afxwin.h中。
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、高字设为y
CPoint类还定义了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、高字设为cy
CSizet类也重载了+、-、+=、-=、==、!=等运算符来支持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对象之间的运算。还定义了转换符LPCRECT和LPRECT来自动完成CRect对象到矩形结构和类指针LPCRECT和LPRECT的转换。
CRect类中常用的属性和成员函数有:
int Width( ) const;
int Height( ) const;
CSize Size( ) const;
CPoint& TopLeft( );
CPoint& BottomRight( );
CPoint CenterPoint( ) const;
void SwapLeftRight();
BOOL IsRectEmpty( ) const;
BOOL PtInRect( POINT point ) const;
void SetRect( int x1, int y1, int x2, int y2 );
void SetRect(POINT topLeft, POINT bottomRight);
void OffsetRect(int x, int y);
void MoveToXY(int x, int y);
3) 判断点是否在矩形中
有时需要判断某点(如鼠标位置)是否在某一矩形区域中,这可以调用CRect类的PtInRect函数来做:
BOOL PtInRect( POINT point ) const;

该函数当点point在其矩形区域内时,返回真。注意,该矩形区域不包括矩形的右边界和底边界。例如:
CRect rect( 10, 10, 371, 267 );

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{
       // TODO: Add your message handler code here and/or call default

       if ( rect.PtInRect( point ) ) {
... ...
       }
... ...
       CView::OnLButtonUp(nFlags, point);
}

2 客户区大小和DC
在绘图前,必须先得到客户区大小和设备上下文DC。
1.获得客户区
绘图一般都是在视图窗口的客户区进行,而客户区的大小在运行时可由用户改变,为了使绘制的图形能随窗口大小自动改变,必须先得到当前客户区大小的数据(宽w和高h)。
获取客户区大小的方法有如下两种:
1)在消息响应函数OnSize中获得
利用属性窗口的信息页,在视图类中添加WM_SIZE消息的响应函数OnSize。该函数在窗口第一次显示或窗口大小被改变时会被Windows系统调用。其输入参数中的cx和cy就是客户区大小的宽和高,可将它们赋值给类变量(如m_iW和m_iH)供绘图时使用。例如
void CDrawView::OnSize(UINT nType, int cx, int cy) {
      CView::OnSize(nType, cx, cy);


      // TODO: 在此处添加消息处理程序代码
      m_iW = cx; m_iH = cy;
}
其中,nType的值为:
<!--[if !supportLists]-->l         <!--[endif]-->SIZE_MAXIMIZED(窗口已被最大化)

<!--[if !supportLists]-->l         <!--[endif]-->SIZE_MINIMIZED(窗口已被最小化)

<!--[if !supportLists]-->l         <!--[endif]-->SIZE_RESTORED(窗口已被改变大小)

<!--[if !supportLists]-->l         <!--[endif]-->SIZE_MAXHIDE(其他窗口被最大化)

<!--[if !supportLists]-->l         <!--[endif]-->SIZE_MAXSHOW(其他窗口从最大化还原)

2)调用成员函数GetClientRect得到
可在绘图前,定义一个矩形变量rect,然后再调用CWnd类的成员函数GetClientRect:
void GetClientRect( LPRECT lpRect ) const;

得到当前客户区矩形的数据,其中的右(right)与底(bottom)就是客户区的宽与高(其左left与顶top都为0)。例如:
       RECT rect;
       GetClientRect(&rect);
       int w = rect.right, h = rect.bottom;
2.DC
在Windows中,绘图使用的是MFC的DC(Device-Context, 设备上下文)类CDC中各种绘图函数。

0)CDC类
CDC是CObject的直接派生类,CDC类自己也有若干派生类,其中包括窗口客户区DC所对应的CClientDC类、OnPaint和OnDraw消息响应函数的输入参数中使用的CPaintDC类、图元文件对应的CMetaFileDC类和整个窗口所对应的CWindowDC类。

CDC类中有许多成员函数,可以用来设置各种绘图环境、属性和参数,以及绘制各种图形和图像等,将在后面陆续加以介绍。
1)获得DC
可以从OnDraw函数的输入参数pDC或调用CWnd的成员函数GetDC:
CDC* GetDC( );

来获得DC的指针。
2)释放DC
因为Windows限制可用DC的数量,所以DC属于稀缺的公用资源。因此,对每次获得的DC,在使用完成后必须立即释放。
从OnDraw函数的输入参数pDC获得的DC,在该函数运行结束后,系统会自动释放。但由GetDC所获得的DC,必须自己来释放,这可以通过调用CWnd的成员函数ReleaseDC来完成:
int ReleaseDC( CDC* pDC ); // 成功返回非0

例如:
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)

{
       ReleaseCapture();
       if (m_bLButtonDown) {
              CDC* pDC = GetDC();
              pDC->SelectObject(new CPen(PS_SOLID, 0, RGB(255, 0, 0)));

              pDC->SelectStockObject(NULL_BRUSH);
              pDC-> Ellipse (rect);
              ReleaseDC(pDC);
              m_bLButtonDown = FALSE;
       }
       CView::OnLButtonUp(nFlags, point);
}
3)类DC
每次从OnDraw函数的输入参数或调用GetDC所获得的DC,都是一个全新的临时缺省DC。它不能用类变量来长期保存,而且原来选入的各种GDI对象全都被作废,必须从头再来。
为了使选入的各种GDI对象一直有效,必须在视图类的PreCreateWindow函数中调用CWnd类的成员函数AfxRegisterWndClass:
LPCTSTR AFXAPI AfxRegisterWndClass( UINT nClassStyle, HCURSOR hCursor = 0,

HBRUSH hbrBackground = 0, HICON hIcon = 0 );

来修改窗口类的风格属性中的DC为类DC:CS_CLASSDC。如
BOOL CDrawView::PreCreateWindow(CREATESTRUCT& cs) {
    cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW |

CS_VREDRAW | CS_CLASSDC, 0,

::CreateSolidBrush(RGB(255, 255, 255)));
       return CView::PreCreateWindow(cs);

}
4)安全DC句柄
也可以用CDC类的成员函数:
HDC GetSafeHdc();

来获取CD所对应窗口(如客户区)的安全DC句柄,该句柄在窗口存在期间一直是有效的。例如,可先定义类变量HDC m_hDC;,再在适当的地方给它赋值m_hDC = GetDC()->GetSafeHdc();,然后就可以放心地使用了。例如,可以使用CDC类的成员函数

BOOL Attach(HDC hDC); // 成功返回非0

来将CDC对象与DC句柄连接在一起。
3 设置绘图颜色
1.颜色
Windows中的颜色一般用4个字节表示(0BGR(整数) = R G B 0(字节序) [Intel CPU低位字节在前]),Win32 API中定义了一个专门表示颜色索引值的变量类型COLORREF:(windef.h)
typedef DWORD COLORREF; // 0x00bbggrr

和一个由红绿蓝三原色构造颜色值的宏RGB:(wingdi.h)
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))

其中,r、g、b为字节变量,取值范围为0~255。其函数说明为:
COLORREF RGB(
BYTE bRed,    // red component of color

BYTE bGreen, // green component of color
BYTE bBlue    // blue component of color

);
例如:
              COLORREF red, gray;

              red = RGB(255, 0, 0);

              gray = RGB(128, 128,128);

在API中还定义了由COLORREF变量获取各个颜色分量的宏Get?Value:(wingdi.h)
#define GetRValue(rgb) (LOBYTE(rgb))

#define GetGValue(rgb) (LOBYTE(((WORD)(rgb)) >> 8))

#define GetBValue(rgb) (LOBYTE((rgb)>>16))

其中:
typedef unsigned long ULONG_PTR;
typedef ULONG_PTR DWORD_PTR;

#define LOBYTE(w) ((BYTE)((DWORD_PTR)(w) & 0xff))
它们对应的函数说明为:
BYTE GetRValue(DWORD rgb); // DWORD rgb ~ COLORREF col
BYTE GetGValue(DWORD rgb);
BYTE GetBValue(DWORD rgb);
2.点色(像素)
在Windows中,像素(pixel)的颜色是直接由设备上下文类CDC的成员函数SetPixel来设置的,该函数的原型为:
COLORREF SetPixel( int x, int y, COLORREF crColor );
COLORREF SetPixel( POINT point, COLORREF crColor );
其中,x与y分别为像素点的横坐标与纵坐标,crColor为像素的颜色值。例如:
pDC->SetPixel(10, 10, RGB(0, 255, 0));

       另外,也可以用CDC的成员函数
COLORREF GetPixel( int x, int y ) const;
COLORREF GetPixel( POINT point ) const;
来获得指定点(x, y)或point的颜色。例如:
    COLORREF col;
    col = pDC->GetPixel(10, 10);
3.线色(笔)
在Windows中,线状图必须用笔(pen)来画,所以线的颜色就由笔色来确定。在MFC中,笔的属性和功能由CPen类提供(CPen是CGDIObject的派生类)。
笔的创建与使用的步骤为:
<!--[if !supportLists]-->l         <!--[endif]-->创建笔对象:创建笔类CPen对象的方法有如下两种:

<!--[if !supportLists]-->n         <!--[endif]-->使用构造函数CPen

CPen( int nPenStyle, int nWidth, COLORREF crColor );

其中:
<!--[if !supportLists]-->u       <!--[endif]-->nPenStyle为笔的风格,可取值:

PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PSDASHDOTDOT



注意:1~4号笔风格只是在笔宽=0或1时有效,笔宽>1时总为实心的。
<!--[if !supportLists]-->u       <!--[endif]-->nWidth为笔宽,与映射模式有关,使用缺省映射时为像素数,若nWidth = 0,则不论什么映射模式,笔宽都为一个像素;

<!--[if !supportLists]-->u       <!--[endif]-->crColor为笔的颜色值。

例如
CPen* pGrayPen = new CPen(PS_SOLID, 0, RGB(128, 128, 128));
CPen grayPen(PS_SOLID, 0, RGB(128, 128, 128));
<!--[if !supportLists]-->n         <!--[endif]-->使用成员函数CreatePen

BOOL CreatePen( int nPenStyle, int nWidth, COLORREF crColor );

如:
CPen grayPen;
grayPen.CreatePen(PS_SOLID, 0, RGB(128, 128, 128));
<!--[if !supportLists]-->n         <!--[endif]-->缺省的笔为单像素宽的实心黑色笔

<!--[if !supportLists]-->l         <!--[endif]-->将笔对象选入设备上下文:为了能使用我们所创建的笔对象,必须先将它选入设备上下文,这可以调用设备上下文类CDC的成员函数SelectObject来完成:

CPen* SelectObject( CPen* pPen );
返回值为指向原来笔对象的指针(一般将其保存下来,供下次再装入时使用)。如
pOldPen = pDC->SelectObject(&pen);
另外,Windows中有一些预定义的笔对象,可用CDC的另一成员函数SelectStockObject将其选入DC,其函数原型为:
virtual CGdiObject* SelectStockObject( int nIndex );
预定义的笔对象有BLACK_PEN(黑色笔)、WHITE_PEN (白色笔)、NULL_PEN(空笔/无色笔)。例如:
pDC->SelectStockObject(BLACK_PEN);
<!--[if !supportLists]-->l         <!--[endif]-->使用设备上下文画线状图:画线状图以及面状图的边线,所使用的是当前设备上下文中的笔对象。线状图有直线、折线、矩形、(椭)圆(弧)等,详见4)(2)

<!--[if !supportLists]-->l         <!--[endif]-->将笔对象从设备上下文中放出:为了能删除使用过的笔对象,必须先将它从设备上下文中释放出来后,然后才能删除。释放的方法是装入其他的笔对象(一般是重新装入原来的笔对象)。例如

pDC->SelectObject(pOldPen);
<!--[if !supportLists]-->l         <!--[endif]-->删除笔对象:为了能删除笔对象,必须先将其从设备上下文中释放。删除方法有如下几种:

<!--[if !supportLists]-->n         <!--[endif]-->调用笔类CDC的成员函数DeleteObject删除笔的当前内容(但是未删除笔对象,以后可再用成员函数CreatePen在笔对象中继续创建新的笔内容)。如

pen.DeleteObject();
<!--[if !supportLists]-->n         <!--[endif]-->使用删除运算符delete将笔对象彻底删除,如delete pen;

<!--[if !supportLists]-->n         <!--[endif]-->自动删除:若笔对象为局部变量,则在离开其作用域时,会被系统自动删除

下面为一段较完整地创建与使用笔的例子代码:
       CPen pen, *pOldPen;
       for (int j = 0; j <= 255; j++) {

              HSLtoRGB(m_hue, m_sat, 255 - j, r, g, b); // 自定义的函数

              pen.CreatePen(PS_SOLID, 0, RGB(r, g, b));

              pOldPen = pDC->SelectObject(&pen);

              pDC->MoveTo(0, j); pDC->LineTo(40, j);

              pDC->SelectObject(pOldPen);
              pen.DeleteObject();
       }
4.面色(刷)
在Windows中,面状图必须用刷(brush)来填充,所以面色是由刷色来确定的。MFC中的刷类为CBrush(它也是CGDIObject的派生类),刷的创建与使用的步骤与笔的相似。
<!--[if !supportLists]-->l         <!--[endif]-->构造函数有4个:

<!--[if !supportLists]-->n         <!--[endif]-->CBrush( ); // 创建一个刷的空对象

<!--[if !supportLists]-->n         <!--[endif]-->CBrush( COLORREF crColor ); // 创建颜色为crColor的实心刷

<!--[if !supportLists]-->n         <!--[endif]-->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 斜十字线(斜网格)


<!--[if !supportLists]-->n         <!--[endif]-->CBrush( CBitmap* pBitmap ); // 创建位图为pBitmap的图案刷

如:pDC->FillRect( &rect, new CBrush( RGB(r, g, b) ) );

<!--[if !supportLists]-->l         <!--[endif]-->与构造函数相对应,有多个创建不同类型刷的成员函数:

<!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateSolidBrush( COLORREF crColor );

<!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateHatchBrush( int nIndex, COLORREF crColor );

<!--[if !supportLists]-->n         <!--[endif]-->BOOL CreatePatternBrush( CBitmap* pBitmap );

<!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateDIBPatternBrush( HGLOBAL hPackedDIB, UINT nUsage );

<!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateDIBPatternBrush( const void* lpPackedDIB, UINT nUsage );

<!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateBrushIndirect( const LOGBRUSH* lpLogBrush );

<!--[if !supportLists]-->n         <!--[endif]-->BOOL CreateSysColorBrush( int nIndex );

<!--[if !supportLists]-->l         <!--[endif]-->预定义的刷对象有BLACK_BRUSH(黑刷)、DKGRAY_BRUSH(暗灰刷)、GRAY_BRUSH(灰刷)、HOLLOW_BRUSH(空刷)、LTGRAY_BRUSH(亮灰刷)、NULL_BRUSH(空刷)、WHITE_BRUSH(白刷)

<!--[if !supportLists]-->l         <!--[endif]-->缺省的刷为空刷

<!--[if !supportLists]-->l         <!--[endif]-->与笔一样,可以用函数SelectObject或SelectStockObject将自定义的刷或预定义的刷选入DC中,供绘面状图时使用。

5.文本色
可使用CDC类的成员函数SetTextColor和SetBkColor来分别设置输出文本的前景色和背景色:(缺省的前景色为黑色,背景色空)
COLORREF GetTextColor( ) const;
virtual COLORREF SetTextColor( COLORREF crColor );
COLORREF GetBkColor( ) const;
virtual COLORREF SetBkColor( COLORREF crColor );
例如:
       pDC->TextOut(10, 10, "Test text");

       pDC->SetTextColor(RGB(0, 128, 0)); pDC->TextOut(10, 30, "Test text");

       pDC->SetBkColor(RGB(0, 0, 128));     pDC->TextOut(10, 50, "Test text");

6.绘图工具
1)GDI对象
Windows的图形设备接口(GDI = graphics device interface)对象指各种绘图工具,如笔、刷、位图、字体、调色板、区域等,对应的MFC类为CPen、CBrush、CBitmap、CFont等。这些图形绘制对象类都是CGDIObject的派生类,而CGDIObject则是直接从CObject类派生的抽象基类。<!--[endif]-->其中,Windws CE不支持调色板类CPalette;CRgn为区域类,对应于窗口中的一个矩形、多边形或(椭)圆区域(region),可用于移动、拷贝、合并、判断和裁剪。

2)选入
可用设备上下文类CDC的多态成员函数SelectObject,来将绘图工具对象选入设备上下文,以供绘图时使用:
CPen* SelectObject( CPen* pPen );
CBrush* SelectObject( CBrush* pBrush );
virtual CFont* SelectObject( CFont* pFont );
CBitmap* SelectObject( CBitmap* pBitmap );
int SelectObject( CRgn* pRgn );
CGdiObject* SelectObject( CGdiObject* pObject );
3)获取
可用API函数GetCurrentObject来获得当前在DC中的指定类型的绘图对象:
HGDIOBJ GetCurrentObject(
HDC hdc,           // handle to device context

UINT uObjectType   // specifies the object-type

);
其中,参数uObjectType可取值:
OBJ_PEN      // Returns the current selected pen.

OBJ_BRUSH // Returns the current selected brush.
OBJ_PAL       // Returns the current selected palette.

OBJ_FONT // Returns the current selected font.

OBJ_BITMAP // Returns the current selected bitmap.
也可分别调用CDC类的下列成员函数来做同样的事:
CPen* GetCurrentPen( ) const;

CBrush* GetCurrentBrush( ) const;

CFont* GetCurrentFont( ) const;

CBitmap* GetCurrentBitmap( ) const;

CPalette* GetCurrentPalette( ) const;

如:
HPEN hPen = (HPEN)GetCurrentObject(pDC->m_hDC, OBJ_PEN);

CPen* pPen = CPen::FromHandle(hPen);

等价于:
CPen* pPen = pDC-> GetCurrentPen( );

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值