`
izuoyan
  • 浏览: 9220593 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

MFC图形函数(转载)

阅读更多

. 映射模式与坐标系

1)默认映射模式
映射模式(map mode)影响所有的图形和文本绘制函数,它定义(将逻辑单位转换为设备单位所使用的)度量单位和坐标方向,Windows总是用逻辑单位来绘图。

缺省情况下,绘图的默认映射模式为MM_TEXT,其绘图单位为像素(只要不打印输出,屏幕绘图使用该模式就够了)。若窗口客户区的宽和高分别为w和h像素,则其x坐标是从左到右,范围为0 ~ w-1;y坐标是从上到下,范围为0 ~ h-1

2)设置映射模式
可以使用CDC类的成员函数GetMapMode和SetMapMode来获得和设置当前的映射模式:
int GetMapMode( ) const; // 返回当前的映射模式

virtual int SetMapMode( int nMapMode ); // 返回先前的映射模式

映射模式的nMapMode取值与含义
符号常量
数字常量
x方向
y方向
逻辑单位的大小
MM_TEXT
1
向右
向下
像素
MM_LOMETRIC
2
向右
向上
0.1 mm
MM_HIMETRIC
3
向右
向上
0.01 mm
MM_LOENGLISH
4
向右
向上
0.01 in
MM_HIENGLISH
5
向右
向上
0.001 in
MM_TWIPS
6
向右
向上
1/1440 in
MM_ISOTROPIC
7
自定义
自定义
自定义
MM_ANISOTROPIC
8
自定义
自定义
自定义
可见,除了两种自定义映射模式外,x方向都是向右,y方向也只有MM_TEXT的向下,其余的都是向上,与数学上一致。除了MM_ANISOTROPIC外,其他所有映射模式的x与y方向的单位都是相同的。所有映射模式的逻辑坐标的原点 (0, 0)最初都是在窗口的左上角,但在CScrollView的派生类中,MFC会随用户滚动文档而自动调整逻辑原点的相对位置(改变视点的原点属性)。
3)自定义映射模式
自定义映射模式MM_ISOTROPIC(各向同性,x与y方向的单位必须相同)和 MM_ANISOTROPIC(各向异性,x与y方向的单位可以不同)的单位和方向,可以通过用CDC类的成员函数G/SetWindowExt和 G/SetViewportExt来获取/设置窗口和视口的大小来确定:
CSize GetWindowExt( ) const;

virtual CSize SetWindowExt( int cx, int cy );

virtual CSize SetWindowExt( SIZE size );
CSize GetViewportExt( ) const;

virtual CSize SetViewportExt( int cx, int cy );

virtual CSize SetViewportExt( SIZE size );
其中,cx或size.cx和cy或size.cy分别为窗口/视口的宽度与高度(逻辑单位)。
还可以用CDC类的成员函数SetViewportOrg来设置坐标原点的位置:
virtual CPoint SetViewportOrg( int x, int y );
CPoint SetViewportOrg( POINT point );
例如
void CDrawView::OnDraw(CDC* pDC) {
CRect rect;
GetClientRect(rect);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(1000,1000);

pDC->SetViewportExt(rect.right, -rect.bottom);

pDC->SetViewportOrg(rect.right / 2, rect.bottom /2);

pDC->Ellipse(CRect(-500, -500, 500, 500));

}
将当前的映射模式设置为各向异性自定义映射模式,窗口大小为1000个逻辑单位宽和1000个逻辑单位高,视口大小同当前客户区,视口的坐标原点设置在当前客户区的中央。由于使用了负数作为SetViewportExt函数的第2个参数,所以y轴方向是向上的。
可见,圆被画成了椭圆,x与y方向上的逻辑单位不相同。
4)单位转换
对所有非MM_TEXT映射模式,有如下重要规则:

CDC的成员函数(如各种绘图函数)具有逻辑坐标参数

CWnd的成员函数(如各种响应函数)具有设备坐标参数(如鼠标位置point)

位置的测试操作(如CRect的PtInRect函数)只有使用设备坐标时才有效

长期使用的值应该用逻辑坐标保存(如窗口滚动后保存的设备坐标就无效了)

因此,为了使应用程序能够正确工作,除MM_TEXT映射模式外,其他映射模式都需要进行单位转换。下面是逻辑单位到设备单位(如像素)的转换公式:
x比例因子 = 视口宽度 / 窗口宽度
y比例因子 = 视口高度 / 窗口高度
设备x = 逻辑x * x比例因子 + x原点偏移量
设备y = 逻辑y * y比例因子 + y原点偏移量
Windows的GDI负责逻辑坐标和设备坐标之间的转换,这可以调用CDC类的成员函数LPtoDP和DPtoLP来进行:

void LPtoDP( LPPOINT lpPoints, int nCount = 1 ) const;

void LPtoDP( LPRECT lpRect ) const;
void LPtoDP( LPSIZE lpSize ) const;

void DPtoLP( LPPOINT lpPoints, int nCount = 1 ) const;

void DPtoLP( LPRECT lpRect ) const;
void DPtoLP( LPSIZE lpSize ) const;
例如:

void CDrawView::OnLButtonDown(UINT nFlags, CPoint point) {

CRect rect = m_rect; // 逻辑坐标

CClientDC dc(this);
dc.SetMapMode(MM_LOENGLISH);
dc.LPtoDP(rect); // 转化成设备坐标

if (rect.PtInRect(point)) // 位置的测试操作只有使用设备坐标时才有效

......
}

void CDrawView:: OnMouseMove (UINT nFlags, CPoint point) {

float t,y;

char buf[40];

CDC* pDC = GetDC();

pDC->SetMapMode(MM_HIMETRIC);
pDC->DPtoLP(&point); // 转化成逻辑坐标

t = t1 + (point.x * dt) / w; sprintf(buf, "%.4fs", t); pSB->SetPaneText(xV, buf);

y = (y0 - point.y) / dy; sprintf(buf, "%.4f", y); pSB->SetPaneText(yV, buf);
......
}
2. 画像素点
画像素点就是设置像素点的颜色,从前面3)(2)已知道这可由CDC的成员函数SetPixel来做,该函数的原型为:

COLORREF SetPixel( int x, int y, COLORREF crColor );

COLORREF SetPixel( POINT point, COLORREF crColor );

其中,x与y分别为像素点的横坐标与纵坐标,crColor为像素的颜色值。例如

pDC->SetPixel(i, j, RGB(r, g, b));

3.画线状图
在Windows中,线状图必须用笔来画(笔的创建与使用见前面的3)(3)),下面是CDC类中可以绘制线状图的常用成员函数:

当前位置:设置当前位置为(x, y)或point:(返回值为原当前位置的坐标)

CPoint MoveTo( int x, int y ); 或 CPoint MoveTo( POINT point );

画线:使用DC中的笔从当前位置画线到点(x, y)或point:(若成功返回非0值):

BOOL LineTo( int x, int y ); 或BOOL LineTo( POINT point );

画折线:使用DC中的笔,依次将点数组lpPoints中的nCount(≥2)个点连接起来,形成一条折线:

BOOL Polyline( LPPOINT lpPoints, int nCount );

画多边形:似画折线,但还会将最后的点与第一个点相连形成多边形,并用DC中的刷填充其内部区域:

BOOL Polygon( LPPOINT lpPoints, int nCount );

画矩形:使用DC中的笔画左上角为(x1, y1)、右下角为(x2, y2)或范围为*lpRect的矩形的边线,并用DC中的刷填充其内部区域:

BOOL Rectangle( int x1, int y1, int x2, int y2 ); 或
BOOL Rectangle( LPCRECT lpRect );
有时需要根据用户给定的两个任意点来重新构造左上角和右下角的点,例如:

rect = CRect(min(p0.x, point.x), min(p0.y, point.y), max(p0.x, point.x), max(p0.y, point.y));

画圆角矩形:使用DC中的笔画左上角为(x1, y1)、右下角为(x2, y2)或范围为*lpRect的矩形的边线,并用宽x3或point.x高y3或point.y矩形的内接椭圆倒角,再用DC中的刷填充其内部区域:

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

int d = min(rect.Width(), rect.Height()) / 4;

pDC-> RoundRect(rect, CPoint(d, d));

画(椭)圆:使用DC中的笔在左上角为(x1, y1)、右下角为(x2, y2)或范围为*lpRect的矩形中画内接(椭)圆的边线,并用DC中的刷填充其内部区域:

BOOL Ellipse( int x1, int y1, int x2, int y2 );
BOOL Ellipse( LPCRECT lpRect );
注意,CDC中没有画圆的专用函数。在这里,圆是作为椭圆的(宽高相等)特例来画的。

画弧:(x1, y1)与(x2, y2)或lpRect的含义同画(椭)圆,(x3, y3)或ptStart为弧的起点,(x4, y4)或ptEnd为弧的终点:(逆时针方向旋转)

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 );

BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4);

BOOL ArcTo(LPCRECT lpRect, POINT ptStart, POINT ptEnd);
画圆弧:(其中(x, y)为圆心、nRadius为半径、fStartAngle为起始角、fSweepAngle为弧段跨角)

BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle);

画弓弦:参数的含义同上,只是用一根弦连接弧的起点和终点,形成一个弓形,并用DC中的刷填充其内部区域:

BOOL Chord( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 );

BOOL Chord( LPCRECT lpRect, POINT ptStart, POINT ptEnd );
4.画填充图
在Windows中,面状图必须用刷来填充(刷的创建与使用见前面的3)(4))。上面(2)中的Polygon、Rectangle、Ellipse和Chord等画闭合线状图的函数,只要DC中的刷不是空刷,都可以用来画对应的面状图(边线用当前笔画,内部用当前刷填充)。下面介绍的是CDC类中只能绘制面状图的其他常用成员函数:

画填充矩形:用指定的刷pBrush画一个以lpRect为区域的填充矩形,无边线,填充区域包括矩形的左边界和上边界,但不包括矩形的右边界和下边界:

void FillRect( LPCRECT lpRect, CBrush* pBrush );

画单色填充矩形:似FillRect,但只能填充单色,不能填充条纹和图案:

void FillSolidRect( LPCRECT lpRect, COLORREF clr );
void FillSolidRect( int x, int y, int cx, int cy, COLORREF clr );

画饼图(扇形):参数含义同Arc,但将起点和终点都与外接矩形的中心相连接,形成一个扇形区域,用DC中的刷填充整个扇形区域,无另外的边线:

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 );

画拖动的矩形:先擦除线宽为sizeLast、填充刷为pBrushLast的原矩形lpRectLast,然后再以线宽为size、填充刷为pBrush画新矩形lpRectLast。矩形的边框用灰色的点虚线画,缺省的填充刷为空刷:

void DrawDragRect( LPCRECT lpRect, SIZE size, LPCRECT lpRectLast,

SIZE sizeLast, CBrush* pBrush = NULL, CBrush* pBrushLast = NULL );

如:pDC->DrawDragRect(rect, size, rect0, size);

填充区域:

用当前刷从点(x, y)开始向四周填充到颜色为crColor的边界:

BOOL FloodFill(int x, int y, COLORREF crColor); // 成功返回非0

用当前刷从点(x, y)开始向四周填充:

BOOL ExtFloodFill(int x, int y, COLORREF crColor,

UINT nFillType); // 成功返回非0

nFillType = FLOODFILLBORDER:填充到颜色为crColor的边界(同FloodFill);(用于填充内部颜色不同但边界颜色相同的区域)
nFillType = FLOODFILLSURFACE:填充所有颜色为crColor的点,直到碰到非crColor颜色的点为止。(点(x, y)的颜色也必须为crColor),(用于填充内部颜色相同但边界颜色可以不同的区域)。例如:

pDC->ExtFloodFill(point.x, point.y, pDC->GetPixel(point), FLOODFILLSURFACE);

5.清屏
Windows没有提供专门的清屏函数,可以调用CWnd的下面两个函数调用来完成该功能:
void Invalidate(BOOL bErase = TRUE);
void UpdateWindow( );
或调用CWnd的函数
BOOL RedrawWindow(

LPCRECT lpRectUpdate = NULL,

CRgn* prgnUpdate = NULL,

UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE

);
来完成。
例如(菜单项ID_CLEAR的事件处理函数):
CDrawView::OnClear() { // 调用OnDraw来清屏
//Invalidate();
//UpdateWindow( );
RedrawWindow( );
}
也可以用画填充背景色矩形的方法来清屏,如:
RECT rect;
GetClientRect(&rect);

pDC->FillSolidRect(&rect, RGB(255, 255, 255));

分享到:
评论

相关推荐

    VC++6.0 MFC图形函数大全

    VC++6.0 MFC 图形函数大全 VC++6.0 MFC 图形函数大全是指利用 VC++6.0 和 MFC(Microsoft Foundation Classes)技术实现的图形函数的集合。这些函数可以帮助开发者快速创建图形应用程序,例如绘制图形、处理事件、...

    mfc图形界面函数

    MFC 图形界面函数 MFC 图形界面函数是 MFC 框架中的一部分,用于创建和管理图形用户界面。这些函数提供了常用的界面控件和功能,使得开发者可以快速创建复杂的图形界面。 1.CButton::Create 函数 CButton::Create...

    mfc 三角函数 绘制

    本项目的核心是利用MFC的图形功能来展示三角函数的图像,如正弦、余弦和正切等。 首先,我们要了解MFC中的CView类,它是MFC框架中负责图形输出的基础类。我们通常会继承自CView,重写OnDraw()成员函数,这是MFC应用...

    MFC各种画图函数的使用方法实例

    总的来说,"MFC各种画图函数的使用方法实例"这个主题涵盖了MFC图形绘制的基本操作,通过实践这些函数,开发者可以创建出丰富的图形用户界面。理解并熟练运用这些函数,对于构建具有复杂绘图功能的MFC应用程序至关...

    mfc绘制数学函数图像

    基于MFC编写一个单文档程序,在客户区用图形来展现各种数学函数曲线。 具体要求: 1)可绘制常见的数学函数曲线,如三角函数、指数函数、幂函数等。 2)通过菜单选择不同的函数曲线类型,可以通过对话框指定该函数的...

    MFC图形平滑移动_lungs3x7_MFC图形平滑移动_

    当用户与图形界面交互时,MFC会将这些事件转化为消息,然后调用相应的成员函数进行处理。在我们的例子中,"EOG_Test_Dlg.cpp"和"EOG_Test_Dlg.h"很可能是对话框类的实现和定义,包含了图形界面的逻辑和控件。 在MFC...

    MFC 图形学 课程设计 程序 源代码

    在本课程设计中,我们将深入探讨MFC(Microsoft Foundation Classes)框架下的图形学编程。MFC是微软提供的一套C++类库,用于简化Windows应用程序的开发,它封装了Windows API,使得开发者能够更容易地创建功能丰富...

    MFC.zip_MFC_MFC 图形编辑器_MFC图形_MFC图形编辑器_MFC平移

    开发者可能需要使用到`OffsetRect`函数或者直接改变`CRect`对象的左上角和右下角坐标,来达到移动图形的目的。 MFC库提供了丰富的控件和机制来支持这些功能。例如,`CView`类是MFC中的视图类,通常用于处理绘图和...

    MFC图形在文档中的保存

    在Microsoft Foundation Classes (MFC)库中,图形绘制和文档保存是两个重要的概念。MFC是微软为Windows应用程序开发提供的一套C++类库,它极大地简化了Windows API的使用,使得开发者能够更加高效地创建复杂的...

    MFC主要函数和类大全.zip

    总的来说,这份"MFC主要函数和类大全"资源是学习和查询MFC的重要参考资料,它能帮助开发者快速掌握MFC的基本概念、类库结构以及关键函数的使用,从而提高Windows应用开发的效率和质量。对于想要深入理解和使用MFC的...

    MFC函数速查工具

    **MFC函数速查工具详解** MFC(Microsoft Foundation Classes)是微软开发的一个C++类库,它基于面向对象编程,用于简化Windows应用程序的开发。MFC提供了许多封装的Windows API函数,使得开发者可以更方便地操作...

    mfc图形长宽变换

    MFC中的CWnd类提供了一个OnPaint()函数,这是我们进行图形绘制的主要入口。我们需要重写这个函数,使用CDC(Device Context)对象来绘制图形。例如,可以使用MoveTo()和LineTo()函数绘制线条,或者Ellipse()、...

    MFC图形

    例如,一个常见的做法是在OnDraw成员函数中实现图形的绘制逻辑。 总结起来,MFC图形是MFC框架提供的一套强大且灵活的图形绘制工具,它使开发者能够以面向对象的方式处理Windows图形界面的各个方面,极大地提高了...

    吉林大学MFC图形学实验课

    3. 图形渲染:通过MFC的OnDraw函数,你可以实现自定义的绘图逻辑,如绘制二维图形、实现基本的图形变换(旋转、平移、缩放)以及图形的碰撞检测等。 4. 用户交互:MFC提供了丰富的消息处理机制,使你能响应鼠标和...

    MFC图形编程教程

    简易的MFC图形编程教程

    计算机图形学 MFC封装函数绘制简单图形

    在这个实验中,我们将专注于如何利用MFC来封装C++函数,以绘制简单的图形。 MFC是微软为了简化Windows API的使用而设计的,它将底层的Win32 API进行了封装,使得开发者可以更加高效地进行图形绘制、事件处理等任务...

    MFC图形及界面编程实例

    本实例聚焦于"MFC图形及界面编程",特别是如何使用MFC来创建和管理对话框(Dialog)。 在Windows程序设计中,对话框是一种重要的交互方式,用户可以通过对话框输入或选择信息,程序则通过对话框接收用户的指令。在...

    mfc下实现回调函数

    在Microsoft Foundation Classes (MFC) 中,回调函数是一种特殊类型的函数,它允许用户代码与库或操作系统进行交互,尤其是在处理异步事件时。回调函数通常作为参数传递给其他函数,以便在特定事件发生时调用。在MFC...

    MFC图形编程教程,有各种绘图实例

    在MFC工程中,`OnDraw()`函数是处理图形绘制的主要场所。当你在`OnDraw()`函数中编写绘图代码,并编译运行程序时,就可以看到屏幕上显示的图形效果。例如,创建一个简单的单文档应用程序,可以模拟记事本的功能;...

Global site tag (gtag.js) - Google Analytics