`
sabolasi
  • 浏览: 909741 次
文章分类
社区版块
存档分类
最新评论

MFC GDI坐标映射例解

 
阅读更多

1)建立单文档MFC项目DrawNewàProjectsàMFC AppWizard(EXE)àSingle Document

2)找到CMainFrame::PreCreateWindow函数,在其中设置默认窗口大小为400 pixel*300 pixel

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

if( !CFrameWnd::PreCreateWindow(cs) )

return FALSE;

// TODO: Modify the Window class or styles here by modifying

// the CREATESTRUCT cs

cs.cx=400;

cs.cy=300;

return TRUE;

}

3)添加OnPaint事件

资源管理器àClassViewà右击CDrawView 选择Add Windows Message Handler

àWM_PAINTàAdd Handler

1. void CDrawView::OnPaint()

2. {

3. CPaintDC dc(this); // device context for painting

4. // TODO: Add your message handler code here

5. CRect cr;//矩形结构

6. GetClientRect(&cr);//获得客户区窗口

7. int cx=cr.right;//

8. int cy=cr.bottom;//

9. dc.SetMapMode(MM_ISOTROPIC);//X=Y

10. dc.SetWindowExt(1000,1000);//设置逻辑窗口,默认窗口原点为(00

11. dc.SetViewportExt(cx,-cy);//定义输出视口,XY上为正

12. dc.SetViewportOrg(cx/2,cy/2);//定义视口原点为客户区中心

13. dc.Ellipse(-200,200,200,-200);//绘制椭圆与客户区外切的椭圆

14. //绘制水平垂直的四条半径

15. dc.MoveTo(0,0); dc.LineTo(200,0);

16. dc.MoveTo(0,0); dc.LineTo(-200,0);

17. dc.MoveTo(0,0); dc.LineTo(0,200);

18. dc.MoveTo(0,0); dc.LineTo(0,-200);

19. //执行F5进行Debug,在底端Output窗口中可以观察ClientRect

20. TRACE( "ClientRect.x = %d, ClientRect.y = %d/n", cx, cy );

21. }

运行结果如图1左。当改变窗口大小时,图中圆形状始终不变。

<1>将上面代码的第9行改为:dc.SetMapMode(MM_ANISOTROPIC);//X!=Y运行结果如图1右。

1

我们发现,尽管上面代码的第13dc.Ellipse(-200,200,200,-200);中定义的椭圆外接矩形逻辑上为正方形,但是显示的并不是圆,而是椭圆。

当我们改变窗口大小时,图中椭圆变形,甚至可能变为圆形。具体为:

保持窗口宽度不变时,减小高度,椭圆变得更扁;保持窗口高度不变时,减小宽度,椭圆变得更圆,当拉伸到客户区为正方形时,我们发现椭圆变成了圆!

<2>将上面代码的第9行改回dc.SetMapMode(MM_ISOTROPIC);//X=Y,第15行改为dc.LineTo(500,0); 18行改为dc.LineTo(0,-500); 运行结果如图2左。

保持窗口高度不变,减小窗口宽度,使窗口宽度<窗口高度,运行结果如图2右。

2

<3>在将<2>中代码的第9行改回dc.SetMapMode(MM_ANISOTROPIC);//X!=Y,运行结果如图3

3

当我们改变窗口大小时,dc.LineTo(500,0); dc.LineTo(0,-500);都是由原点(客户区中心)到客户区右端中心、底端中心的直线。

<4>将原代码中第10dc.SetWindowExt(1000,1000);//设置逻辑窗口后添加dc.SetWindowOrg(100,100);设置逻辑窗口的原点为(100100)。观察运行结果可知,图1中的图形整体向左向下分别移动了100个逻辑单位:

(-200,200,200,-200)——>(-200-100,200-100,200-100,-200-100)

若需要保持图1中的图形,则需要将涉及到的每个点加上(100,100),即:

13. dc.Ellipse(-200+100,200+100,200+100,-200+100);

14. //绘制水平垂直的四条半径

15. dc.MoveTo(0+100,0+100); dc.LineTo(200+100,0+100);

16. dc.MoveTo(0+100,0+100); dc.LineTo(-200+100,0+100);

17. dc.MoveTo(0+100,0+100); dc.LineTo(0+100,200+100);

18. dc.MoveTo(0+100,0+100); dc.LineTo(0+100,-200+100)

(4)总结逻辑窗口坐标到设备视口坐标的映射方法:

<1>逻辑窗口原点映射为视口原点

<2>逻辑窗口宽度和高度映射为视口宽度和高度

<3>当映射方式为MM_ISOTROPIC时,WindowExt.Width=WindowExt.Height,有效绘图区域为以视口宽高中的最小边为边长的正方形区域。比例因子为:

scaleX=scaleY=min{ViewportExt.Width, ViewportExt.Height }/WindowExt.Width

当映射方式为MM_ANISOTROPIC时,有效绘图区域为整个视口(这里为客户区)。比例因子为:

scaleX=ViewportExt.Width/WindowExt.Width

scaleY=ViewportExt.Height /WindowExt.Height。见图4.

<4>设备(视口)坐标 = (逻辑坐标逻辑窗口原点坐标)×比例因子+视口原点坐标

4

以下分析中客户区大小为ClientRect=(388200),逻辑窗口原点为WindowOrg=(100,100),基于(3<4>中修改后的代码。

在上图4左中,nMapMode=MM_ISOTROPIC,椭圆外接矩形左上角逻辑坐标(-100,300)映射为客户区的以Pixel为单位的坐标为:

left_top_X= (-100-100)×(200/1000+388/2=154 pixel

left_top_Y= (300-100)×(200/1000+200/2=140 pixel

依此次方法可计算出右下角逻辑坐标(300,-100)映射为客户区的以Pixel为单位的坐标为:

right_bottom_X=234 pixel;right_bottom_Y=60 pixel

我们若在第9dc.SetMapMode(MM_ISOTROPIC);//X=Y前添加CreatePen(PS_SOLID,2,RGB(255,0,0));dc.Ellipse(154,140,234,60);则可以发现,这个以2个像素宽的红色画笔绘制的()圆刚好和设置映射模式后绘制的()圆重合。但是我们改变窗口大小时,发现设置映射模式后绘制的()圆按比例拉伸,但红色圆始终在原地且大小保持不变,这也说明了默认映射方式MM_TEXT是以X轴正方向朝右,Y轴正方向朝下的坐标系和1 pixel为单位进行绘制的。

同理,我们可以分析上图4右中,nMapMode=MM_ANISOTROPIC的情况下,CRect(116,140,272,60);为等效椭圆外接矩形。

分享到:
评论

相关推荐

    MFC GDI绘图基础

    一.关于GDI的基本概念 什么是GDI? .../* Mapping Modes */定义了DC中的坐标映射方式,包括以下常用函数: SetMapMode、SetViewportExtEx、SetViewportOrgEx、 SetWindowExtEx 、SetWindowOrgEx。

    精通MFC (光盘) 源代码

    11.1.4 坐标变量和坐标映射 11.2 绘制图形 11.2.1 画线 11.2.2 绘制矩形 11.2.3 绘制椭圆 11.2.4 绘制弧线 11.2.5 绘制多边形 11.2.6 绘制贝济埃样条 11.2.7 使用路径 11.2.8 填充 11.2.9 区域 11.3 ...

    深入浅出MFC【侯捷】

    配置GDI绘图工具 尺寸与方向:关于映射方式(坐标系统) 分页 页眉与页脚 动态计算页码 打印预览(Print Preview) 本章回顾 第13章 多重文件与多重显示 MDI和SDI 多重显示(Multiple Views) 窗口的动态切分 窗口的...

    深入浅出MFC 2e

    简化的MFC程序结构——以Hello MFC为例 Hello程序程序代码 MFC程序的来龙去脉(causal relations) 我只借用两个类:CWinApp和CFrameWnd CWinApp——取代WinMain的地位 CFrameWnd——取代WndProc的地位 引爆器——...

    MFC教程入门知识全集.rar

    4.5 MFC 消息映射机制 4.5.1 消息的种类 4.5.2 应用程序的Run 函数 4.5.3 消息映射表 4.5.4 如何添加消息映射 4.6 ClssWizard 的使用 4.6.1 ClssWizard 概貌 4.6.2 如何添加消息处理函数 4.6.3 如何添加成员...

    C++MFC教程

    在MFC中对消息的处理利用了消息映射的方法,该方法的基础是宏定义实现,通过宏定义将消息分派到不同的成员函数进行处理。下面简单讲述一下这种方法的实现方法: 代码如下 BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd...

    侯捷- -深入浅出MFC

    简化的MFC程序结构——以Hello MFC为例 Hello程序程序代码 MFC程序的来龙去脉(causal relations) 我只借用两个类:CWinApp和CFrameWnd CWinApp——取代WinMain的地位 CFrameWnd——取代WndProc的地位 引爆器——...

    VC++ 一些GDI图形操作相关源码实例

    内容索引:VC/C++源码,图形处理,GDI 一些与GDI相关的程序示例代码,内容主要有创建屏幕DC、绘制图形、获得其他程序的图标、获得文本的长度和高度、坐标映射、设置背景模式、设置文本的对齐方式、实现“橡皮筋”功能...

    VC 使用双缓冲和GDI做的时钟

    VC 2010开发,Win32程序,无需MFC支持. 看完这个例子,你至少能掌握以下知识点 (1) GDI和GDI+的混合编程 (2) 坐标旋转,窗口和视口的关系 (3) 映射模式 (4) 双缓冲技术避免窗体闪烁 ...

    Windows编程中的图形输出 (2006年)

    在Windows编程中要想使用GDI对图形进行输出,首先就必须理解设备上下文、当前作图工具(如什么样的线、什么样的刷子和什么样的字体等)以及如何把GDI逻辑坐标映射到设备坐标等概念.通过围绕上述几个概念对Windows编程中...

    visual c++ 开发宝典 源码

    9.6 根据坐标绘制三角形 小结 第10章 对话框 10.1 对话框的创建 10.1.1 对话框的创建流程 10.1.2 创建对话框资源 10.1.3 对话框窗口布局 10.1.4 创建对话框类和菜单栏制作 …… 第3篇 深入学习篇 第4篇 专业项目...

    Windows编程技术

    5.1 GDI与MFC 86 5.1.1 概述 86 5.1.2 设备环境类 87 5.1.3 GDI对象类 87 5.2 绘制图形 88 5.2.1 开始绘图 88 5.2.2 更改画笔 91 5.2.3 使用画刷 92 5.2.4 使用位图 93 5.3 输出文本 99 5.3.1 文本输出函数 99 5.3.2...

    Visual.C#2010从入门到精通

    第7章 MFC消息映射与消息传递机制 108 7.1 消息概述 108 7.1.1 队列消息和非队列消息 108 7.1.2 系统消息和应用程序消息 109 7.1.3 窗口消息、命令消息和控件通知 109 7.2 MFC消息映射机制 110 7.2.1 MFC消息处理 ...

    Visual C++2010开发权威指南(共三部分).part1.rar

    6.6.2 坐标换算 319 6.6.3 限制图形大小 322 6.6.4 改变鼠标光标 325 6.7 Visual C++ 2010 HtmlEditView开发 328 6.8 Visual C++ 2010 HtmlView开发 331 6.9 Visual C++ 2010 ListView开发 335 6.10 Visual C++ 2010...

Global site tag (gtag.js) - Google Analytics