c++1.doc_第1页
c++1.doc_第2页
c++1.doc_第3页
c++1.doc_第4页
c++1.doc_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

CRect类介绍注意:这个类是从tagRECT结构派生而来的。(tagRECT是RECT结构的不太常用的别名。)这意味着RECT结构的数据成员(left,top,right,和bottom)也是CRect的可访问数据成员。 一个CRect包含用于定义矩形的左上角和右下角点的成员变量。 当指定一个CRect时,必须谨慎地构造它,以使它符合规范也就是说,使其左坐标值小于右坐标值,使顶坐标值小于底坐标值。例如,左上角为(10,10),右下角为(20,20)就定义了一个符合规范的矩形,但是左上角为(20,20)而右下角为(10,10)的值就定义了一个不符合规范的矩形。如果矩形是不符合规范的,则CRect的许多成员函数都会符合不正确的结果。(参见CRect:NormalizeRect可以得到这些函数的列表。)在你调用一个要求符合规范的矩形的函数之前,你可以通过调用NormalizeRect函数来使不符合规范的矩形成为符合规范的矩形。 当用成员函数CDC:DPtoLP和CDC:LPtoDP来处理CRect时要小心。如果显示环境的映射模式y-extent是负的,就像在MM_LOENGLISH中一样,则CDC:DPtoLP将转换CRect,以使它的顶部坐标大于底部坐标。然后像Height和Size这样的函数将返回负值作为转换后的矩形的高度,则此矩形将是不符合规范的。 当使用重载的CRect操作符时,第一个操作数必须是一个CRect;第二个操作数可以是一个RECT结构或一个CRect对象。CRect类介绍及GetClientRect函数功能该函数获取窗口客户区的坐标。客户区坐标指定客户区的左上角和右下角。由于客户区坐标是相对窗口客户区的左上角而言的,因此左上角坐标为(0,0) 函数原型 在Win32 SDK, 该API函数原型为 BOOL GetClientRect( HWND hWnd, / 窗口句柄 LPRECT lpRect / 客户区坐标 ); 在MFC中,该函数的原型为void GetClientRect(LPRECT lpRect) const; 参数 hWnd:是程序窗口的句柄。 lpRect:是一个指针,指向一个RECT类型的rectangle结构。该结构有四个LONG字段,分别为left、top、right和bottom。GetClientRect将这四个字段设定为窗口显示区域的尺寸。left和top字段通常设定为0。right和bottom字段设定为显示区域的宽度和高度(像素点数)。 也可以是一个CRrect对象指针。CRect对象有多个参数,与RECT用法相同。 函数的作用总的来说就是把客户区的大小写进第二个参数所指的Rect结构当中。 返回值 如果函数成功,返回一个非零值。 如果函数失败,返回零。要得到更多的错误信息,请使用GetLastError函数 VC+技术内幕学习笔记(1) 写在前面:我看的VC+技术内幕版本为-潘爱民和王国印译清华大学出版的第四版,因从网上看到此版译的最好。这篇学习笔记是后补的,因为这本书我已经看到了第三十二章,之前并没有做笔记,只是随意的在书上画了画重点,可是越向后学越觉得前面的知识并没有掌握,所以决定重新来过并补上笔记。我认为只有踏踏实实的记录下每天的学习心得才能真正的有所收获。我个人认为学习这本经典之前最好先看看WINDOWS 32位编程的书,至少能用纯SDK写出一些小程序。第一天:WINDOWS应用程序一定要有WinMain函数,该函数用来完成一些特殊的任务,象创建程序的主窗口,主窗口用来处理消息的代码。MFC将WinMain隐藏在框架中,不象写SDK程序时可以很容易的找到它。WINDOWS采用的消息处理机制也交给了程序框架,我们不必担心如何使这些消息和代码联系起来。并且WINDOWS定义好了一些消息,当窗口被创建时系统就会发送WM_CREATE消息,当点击鼠标左键时便系统会发送WM_LBUTTONDOWN消息,当用户按下键盘时系统会发送WM_CHAR消息,当用户关闭窗口时系统会发送WM_CLOSE消息,当用户进行菜单项选择或单击按钮时系统回发送WM_COMMAND消息,什么都不做系统还会发送WM_TIMER消息。先不说别的,先搞清出这几个消息再说。从MSDN中可以很方便的找到关于这几个消息的帮助文档。WINDOWS提供通用的图形设备接口(GUI),我们通过调用(GDI)函数和硬件打交道,不必理会设备环境,WINDOWS会自动将设备环境结构映射到相应的物理设备,这应该就是设备无关性吧。动态连接库(DLL)应该是代码重用的典型例子(不知道可不可这样说),把一些模块、自己新编的类单独调试并编译成DLL,及增加代码的可读性也提高了程序模块的灵活性。用Developer Studio建立项目Developer Studio会创建很多中间文件,这些文件还是有必要说一下的。APS /支持ResourceViewBSC /浏览器信息文件CLW /支持ClassWizardDSP /项目文件,不能删除和用文本编辑器编辑DSW /工作空间文件,不能删除和用文本编辑器编辑MAK /外部的创建文件NCB /支持ClassViewOPT /保存工作空间的配置PLG /建立日志文件这些文件都有一定的作用,拿CLW来说,如果你有一个新类,需要加到ClassWizard中,除了将相应的.h 和.cpp加到DSP中还需要重新编译CLW。PLG文件记录着你的项目配置信息。VC+的源程序浏览器能够使我们从类或函数的角度来了解或编辑程序,而不是直接从文件入手。在看别人的源代码时如果能熟练的使用源代码浏览器将会事倍功半。源程序浏览器主要的查看状态有以下几种:Definitions and References选择任何函数、变量、类型、宏定义可以看到它在项目中的定义,并且在何处和什么地方用到它。Call Graph/Caller Graph对于所选择的函数,给出它的调用与被调用函数的图示。Derived Class Graph/Base Class Graph给出类层次关系的图形表示,可以看到所选择的类的派生类和基类以及成员。File Outline对于所选的文件,列出文件中的类、函数和数据成员,同时还显示它们定义的位置和使用位置。可见Source Brower比起Class View来功能多了很多也更加好用,以前我就不知道,因为一般的VC+书没有讲或根本没有注意这块,看到讲菜单、操作界面、编辑器时总是跳过,心想“没吃过猪肉还没见过猪跑?这种东西不用学就会”。可实际上还是应该仔细的看看的。对于本章学习雷神建议大家在VC+6中用AppWizard生成一个空的程序,然后试着看看都有那些文件,和他们的类层次、函数、宏、结构的定义,我就是这样干的,学编程不动手是不行的 VC+技术内幕学习笔记(2) 第二天:Microsoft基本类库应用程序框架MFC是C+的Microsoft Windows API,如果想要开发WINDOWS的应用程序当然VC/MFC是开发环境的首选。MFC产生的应用程序使用了标准化的结构。(我现在还体会不出这点的优势所在,请高手指点)MFC产生的应用程序短而运行速度快。这应该说的是可以很容易的建立动态连接,其实程序还是需要大量的DLL,不过由于WINDOWS上有很多可以用DLL所以应用程序很短,我是这样想的不知对否。VC+工具降低了编码的复杂性。这点不容质疑比起TC方便太多了。MFC库功能非常丰富。书上列出了MFC从1.0-4.21的一些特性,我就不废话了,大家应该看看。 这一章节主要介绍了MFC库的优点,其实我本人认为在某些特定环境下其实MFC不一定就象说的那样好。我想不会有人用纯VC做MIS系统吧,太累了。我是这样理解编程序的,如果把学编程看成学武的话,C/C+语言及编程思想(OOP)是内功,API是基本功(编程思想是内功、API是基本功这适用于任何WIN32编程,不论Visual C+、Delphi、C+Builder、VB.),VC/MFC应该不同武功其中的一种,不同的学习方法效果不一样,只要下工夫也都可以达到一定的境界。真正的高手是有着深厚的内功,扎实的基本功,至于武功招数无所谓了,随便一站不丁不八全无破绽,无招胜有招了。对不住扯远了。 C+可以通过类库来进行扩展,我们除了可以使用随编译器提供的类库外还可以很方便使用软件公司销售的类库产品,甚至可以自己开发。而应用程序框架是一种类库的超集,它定义了程序的结构。 下面给出两个示例程序(一个是书上的一个是我写的):雷神建议:虽然现在很多书都附CD,CD上有书中所有示例的源代码,但还是应该亲自在VC6用手敲进去。这样可以加深印象以及感受一下编译除错后程序正确运行时的乐趣,因为是纯手工打造。自从我敲了近一百个代码示例后,由于笔误的BUG就很少了,打字速度也提高了。而且最好在原示例代码的基础上做些改动例如别千篇一律的显示HELLO WORLD!换点别的,这样做也可以加深对示例程序的理解。 我的HELLO WORLD用AppWizard向导创建一个显示一个字符串的单文档程序,只需要敲入一行语句,主要是体验MFC的强大功能。1、打开VC+6从菜单选择NEW,给项目命名为”MyApp01“。2、选择MFC AppWizardexe 选项,除STEP 1选择单文档外其他STEP缺省。3、在Class View选择CMyApp01View类的OnDraw()成员函数双击会在C+编译器看到以下内容void CMyApp01View:OnDraw(CDC* pDC)CMyApp01Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data here在 / TODO: add draw code for native data here的位置增加一行代码void CMyApp01View:OnDraw(CDC* pDC)CMyApp01Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);pDC-TextOut(10,10,雷神愿意和所有学VC的朋友共同进步!); /Add to project-Files,分别创建一个名为MyApp.h和一个名为MyApp.cpp的文件。3、添加代码:(最好照敲以下代码到编译器,别用Ctrl+C/Ctrl+V)/*/ MyApp.h/class CMyApp:public CWinApp /见下public:virtual BOOL InitInstance();class CMyFrame:public CFrameWndpublic:CMyFrame();protected:afx_msg void OnLButtonDown(UINT nFlags,CPoint point);afx_msg void OnPaint();DECLARE_MESSAGE_MAP();/*/ MyApp.cpp/#include afxwin.h#include myapp.hCMyApp theApp;/建立一个CMyAPP对象见下BOOL CMyApp:InitInstance ()m_pMainWnd=new CMyFrame();m_pMainWnd-ShowWindow (m_nCmdShow);m_pMainWnd-UpdateWindow ();return TRUE;BEGIN_MESSAGE_MAP(CMyFrame,CFrameWnd)ON_WM_LBUTTONDOWN()ON_WM_PAINT()END_MESSAGE_MAP()CMyFrame:CMyFrame()Create(NULL,MYAPP Application);void CMyFrame:OnLButtonDown (UINT nFlags,CPoint point)TRACE(Entering CMyFrame:OnLButtonDown - %lx,%d,%dn,(long)nFlags,point.x ,point.y);void CMyFrame:OnPaint ()CPaintDC dc(this);dc.TextOut (0,0,Hello World!);4、编译运行,报错。为什么呢?原来还没有添加MFC的支持,在Project Setting选项General属性页选择”Use MFC in a Static Library5、再Ctrl+F5,哈成功了。 VC+技术内幕学习笔记(3) 第三篇:消息映射和视图类 在写了两篇笔记后有很多朋友给我发信,和我交流一些在学习过程中的问题。但由于我也是一个初学者,对一些问题自己也没有把握,所以实在不敢做答,但我会尽量尽我所能和大家一起研究,谢谢大家的鼓励和信任。 在开始先补充一下上一篇的内容“内容窗口的创建”,兼答天歌网友的问题(如果天歌兄弟能看到的话 )。为了简化我们看一个更简单代码,只有一个文件,创建一个空白的窗口,什么也不做。注意哦:真写程序时还是要分成.h和.cpp两个文件比较清晰。 前几步和VC+技术内幕学习笔记(2)中的一样,下面是代码:/*/ MyApp.cpp#include afxwin.h /afxwin.h会调用windows.h是MFC编程的途径,只要用到MFC就一定要包含它。class CMyApp:public CWinApp /从CWinApp继承一个类public:virtual BOOL InitInstance();/重载InitInstance虚函数;class CMyFrame:public CFrameWnd /从CFrameWnd继承一个类;CMyApp myApp; /最后又激活应用程序的构造函数BOOL CMyApp:InitInstance ()m_pMainWnd=new CMyFrame;/new 激活了CMyFrame类构造函数CFrameWnd(),构造函数调又用CREATE()/m_pMainWnd在MFC的定义CWnd* m_pMainWnd;/ main window (usually same AfxGetApp()-m_pMainWnd)/m_pMainWnd保存窗口的位置(CMyFrame * )m_pMainWnd)-Create(NULL,一个MFC应用程序:空白窗口); /创建窗口m_pMainWnd-ShowWindow(m_nCmdShow); /显示在屏幕上return TRUE; 如果还不明白建议查看MSDN或看看侯大师的深入浅出。关于这个问题就说到这,最后对天歌朋友的学习态度表示敬意。下面进入正体,让我们继续来看看MFC的消息映射。 MFC是通过一些宏来将特定的消息影射到派生类相应的成员函数上,这种体制的好处是允许某些非窗口类(如文档类)来控制命令消息。且不需要C+作任何扩展。 MFC的消息控制函数要求提供函数原形、函数体以及消息映射中的入口。真的很麻烦,还好用Class Wizard可以很容易的将上面说到的东西加到我们的类中。例如只要在Class Wizard中添加WM_LBUTTONDOWN消息,则相应的代码便加在合适的地方。怎么样简单多了吧。 应用程序除了包含应用程序框架类外,一般还要包含文档和视图类。这种文档-视图结构是应用框架的核心。我一直做MIS开发,当然不是用VC用的是VB,所以看到这我很不自觉的想到了后台数据库和界面的关系,这个例子可能不是很恰当,但却能很好的帮助我们理解文档和视图。文档好比后台的数据库,视图就是界面上显示的内容,同一个数据库可以用不同的界面显示,但由于所有的界面内容都是从数据库中数据得来,所以当数据库发生变化时所有的相关界面显示都会跟着改变。越来越觉得不恰当,不过实在想不出别的例子了。我们的应用程序实际上就是通过视图对文档进行一系列操作,不单指输出。下面我们看看视图类。 视图是一个从CView类派生的类的对象,在屏幕上显示的窗口就是一种。对象的行为完全由类的成员函数和数据成员决定,其中及包括派生类中的特定函数,也包括基类的标准函数,所以了解MFC类库的结构以及各类的标准成员函数是多么重要啊,别怕麻烦找来MFC的源码读读,看多少算多少,但肯定不白看,这是雷神的经验。记得上一篇的我的例子吗1、打开VC+6从菜单选择NEW,给项目命名为”MyApp01“。2、选择MFC AppWizardexe 选项,除STEP 1选择单文档外其他STEP缺省。此时MFC应用程序框架便帮我们完成了应用程序,你可以执行它,它会在屏幕上显示一个典型的WINDOWS风格的空白窗口。我们来看一下项目程序所在目录下的文件:myapp01.dsp /项目文件myapp01.dsw /工作空间文件myapp01.rc /资源描述文件myapp01View.cpp /包含CMyAppView类成员函数的视图类实现文件 重点myapp01View.h /包含CMyAppView类成员函数的视图类头文件 重点myapp01.opt /二进制文件,告诉Developer Studio本项目的哪些文件是打开的,又是如何排列的readme.txt /用来解释所产生的所有文件,未列出的myapp01Doc.cpp、myapp01Doc.h、StdAfx.cpp、StdAfx.h.在这里都可以找到相应解释。resource.h /包含#define常量定义的头文件 仔细研究一下myapp01View.cpp和myapp01View.h文件,程序核心CMyAppView类在这两个文件中定义,就是我们今天要学的视图类。要想看到CMyAppView类的全貌,应该用Source Browser查看,选择CMyApp01View,按Alt+F12,选择Base Class and Members 选项。我们会看到CMyAppView类的层次关系(从哪来得),以及所有成员函数,包括从基类继承的(在Class View中不能显示父类的成员函数)。我们发现实际上你什么也不用做就拥有了一个有着强大功能的类。 下面我们看一下CMyAppView类的OnDraw成员函数,它是虚函数作用是每当窗口需重绘时应用程序框架会调用它。它的原型是这样的(在myapp01View.h可以找到)virtual void OnDraw(CDC* pDC); / overridden to draw this view 参数是CDC类的指针,WINDOWS是通过和窗口相关联的设备环境(CDC类的对象就是设备环境)和显示硬件进行通讯。有了这个指针我们便可以调用CDC类的成员函数来完成各种绘制工作,如上一篇用到的textout()还有一些Ellipse()、Polygon()、BitBlt()等等在MSDN中有好长的一篇,它是直接从CObject派生的,好了我们开始在OnDraw()里添加一些绘图工作。3、在Class View选择CMyApp01View类的OnDraw()成员函数双击会在C+编译器看到以下内容void CMyApp01View:OnDraw(CDC* pDC)CMyApp01Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data here在 / TODO: add draw code for native data here的位置增加一行代码void CMyApp01View:OnDraw(CDC* pDC)CMyApp01Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);第四篇:资源和编译 资源文件(就是以应用程序名和扩展名是.rc的文件)很大程度上决定了应用程序的用户界面。在VC+中资源文件包括以下内容:Accelerator /模拟菜单和工具栏的选择内容Dialog /对话框的布局及内容Icon /图标有两种一种是16X16一种是32X32。Menu /应用程序的主菜单及所属的弹出式菜单String table /字符串不属于C+源代码部分Toolbar /工具条。Version /程序的描述、版本号、支持语言信息。以上信息都在.rc文件中包含,同时.rc文件还包含了以下语句:#include afxres.h#include afxres.rc 它们的作用是把适合于所有应用程序的一些通用MFC库资源包含进来。 关于资源编辑器的使用就不多说了,因为它的操作很简单,需要注意的是虽然resource.h是一个ASCII码文件可以用文本编辑器进行编辑,单如果使用文本编辑器进行编辑的话,下次再使用资源编辑器时所做的修改有可能丢失,所以我们应该在尽量在资源编辑器中编辑应用程序的资源,新增的资源内容回自动的添加在我们的程序相应位置,例如resource.h而不用我们操心。这便是为什么称为Visual (可视)的原因之一。 编译在VC+中有两种模式,一种是Release Build另一种是Debug Build。它们之间的区别在于,Release Build不对源代码进行调试,不考虑MFC的诊断宏,使用的是MFC Release库,编译十对应用程序的速度进行优化,而Debug Build则正好相反,它允许对源代码进行调试,可以定义和使用MFC的诊断宏,采用MFC Debug库,对速度没有优化。所以我们应该在Debug模式下开发应用程序,然后在Release模式下发布应用程序。在我们的工程文件夹下会有一个Debug文件夹和一个Release文件夹分别存放输出文件和中间文件。 诊断宏是我们编译程序时检测程序状态的有利工具,例如上两篇用到的TRACE宏,可以在Debug窗口获得你需要的诊断信息,而不用设置对话框之类的方法,在发布时Release会自动滤掉此信息。 实际上对一个应用程序的调式是一件很具挑战的工作,我相信我们都有类似的经历,从网上或书本上找来了一段代码或源程序,当我们一点点将他们敲进 Deleloper Studio后进行编译时一下子出现了无数的错误和警告,(有些书的源代码就是错误的)这是需要的耐心和经验,有了VC+提供的调试工具如诊断宏、设断点、单步执行等等,会让我们省不少力气。至于编译的话题其实应该有很多可以说,但由于雷神本身的经验不足只能把书上所讲的作一个总结,大家应该熟练的掌握VC+为我们提供的的各种调试工具,象SPY之类的工具在MSDN中也有很详细的使用帮助说明,到现在我体会到了高手们所说的MSDN是最好的最全的也是最权威的。第五篇:基本事件处理 我们已经知道MFC库应用程序框架调用CView视图类的虚函数OnDraw来完成屏幕显示。其实CView和CWnd类包含了几百个成员函数,在MSDN中可以看到这些成员函数,其中有许多On开头的,例如第二篇的例子就有一个OnLButtonDown,它们都是应用程序框架响应各种事件所需调用的函数。 OnDraw便是当窗口发生变化是被调用的,OnLButtonDown是鼠标左键被按下时调用,还有OnKeyDown是键盘被按下时调用等等。 当用户在视窗中按下鼠标左键时,Windows会自动发送WM_LBUTTONDOWN消息给该视窗,当然你可以什么都不做象我们第3篇的例子一样,如果你想要让程序对此消息做出反应就必须在视图类给出相应的函数,类似下面这样:void CMyView:OnLButtonDown(UINT nFlags,CPoint point)/做些事情的代码还需要在类头文件包含相应的函数原型说明afx_msg void OnLButtonDown(UINT nFlags,CPoint point);afx_msg只是说明该函数原型是针对消息映射函数。下一步在代码文件中还需要有一个消息映射宏,作用是把OnLButtonDown函数和应用程序框架联系在一起。BEGIN_MESSAGE_MAP(CMyView,CView)ON_WM_LBUTTONDOWNEND_MESSAGE_MAP()最后在类库的头文件还需包含:DECLARE_MESSAGE_MAP() 函数和Windows消息的对应关系可以从MSDN中找到在MSDN中索引输入(WM_ Messages)便会列出所有的Windows消息和消息控制函数原型。在实际的编程过程中我们不可能全部都用手工的添加或编制消息控制函数。除了一些特殊的,我们一般是借助Class Wizard来自动编制消息映射函数。这又是MFC应用程序框架比起SDK来的有一个便捷的地方。 MFC库对140种windows消息直接提供了消息控制函数,并且我们还可以自己定义自己的消息,下面列出的五种消息是我们应该特别注意的(MSDN上有更详细的内容)。WM_CREATE 该消息是Windows发给视图的第一个消息。当应用程序框架调用create函数时该消息便会被发送,此时窗口还未创建完成,不可见,因此在消息控制函数OnCreate内不能调用那些依赖窗口处于完全激活状态的Windows函数。如果需要可以在重载的OnInitialUpdate函数内调用。不过注意在SDI应用程序OnInitialUpdate函数可能被多次调用。WM_CLOSE 当用户关闭窗口时,系统会发送WM_CLOSE消息。如果派生类重新定义了OnClose函数,就可以完全控制关闭过程,可以将提醒用户存盘之类的工作放在这里完成。我们可以通过重载CDocument:SaveModified虚函数达到相同的目的。WM_QUERYENDSESSION 从字面的意思看就可以看出,当用户退出Windows时,或者调用了ExitWindows 函数时。Windows会发送WM_QUERYENDSESSION消息给所有的正在运行的应用程序,由OnQueryEndSession消息映射函数对消息进行处理。在它之后应该是WM_ENDSESSION 消息。 WM_DESTROY在Windows发送WM_CLOSE消息后,紧接着会发送WM_DESTROY消息,虽然窗口已经Close但实际上并没有完全清除,在任务管理器中还可以看见应用程序的进程(我想很多木马或病毒都是无窗口的程序,它们的做法是生成了已经活动状态的窗口但不显示出来),利用这个消息控制函数便可以对依赖于当前窗口存在的东西做清除工作,不过一定要注意,应该调用基类的OnDestroy函数,而不能在用户自己的视图的OnDestroy函数中终止窗口的析构过程,终止析构过程应该在OnClose函数中。WM_NCDESTROY 当窗口被取消所发送的最后一个消息就是这个消息。我们可以在OnNcDestroy函数中做一些不依赖该窗口是否处于活动状态的最后的处理工作,(我实在想不出还需要做什么?那位朋友能给个例子),注意一定要调用基类中的OnNcDestroy函数。 我们可以做一个小恶作剧程序:当在窗口内单击鼠标右键(注意是右键)时退出所有的正在运行的应用程序。void CMy007View:OnDraw(CDC* pDC)CMy007Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);pDC-TextOut (100,100,请不要单击鼠标右键,否则后果自负!);void CMy007View:OnRButtonDown(UINT nFlags, CPoint point):MessageBox (NULL,你确定要这样做吗?,警告,1);:ExitWindows ();/web/189/21186.htm映射模式 在此篇之前我们已经学会了在窗口显示图形,更准确的说是在窗口指定位置显示图形或文字,我们使用的坐标单位是象素,称之为设备坐标。看下面语句: pDC-Rectangle(CRect(0,0,200,200); 画一个高和宽均为200个象素的方块,因为采用的是默认的MM_TEXT映射模式,所以在设备环境不一样时,画的方块大小也不一样,在1024*768的显示器上看到的方块会比640*480的显示器上的小(在不同分辨率下的屏幕象素,在WINDOWS程序设计一书中有示例程序可以获得,或者可以用GetClientRect函数获得客户区的矩形大小。在这里就不说了,大家只要知道就行了),在输出到打印机时也会有类似的情况发生。如何做才能保证在不同设备上得到大小一致的方块或者图形、文字呢?就需要我们进行选择模式映射,来转换设备坐标和逻辑坐标。 Windows提供了以下几种映射模式: MM_TEXT MM_LOENGLISH MM_HIENGLISH MM_LOMETRIC MM_HIMETRIC MM_TWIPS MM_ISOTROPIC MM_ANISOTROPIC 下面分别讲讲这几种映射模式: MM_TEXT: 默认的映射模式,把设备坐标被映射到象素。x值向右方向递增;y值向下方向递增。坐标原点是屏幕左上角(0,0)。但我们可以通过调用CDC的SetViewprotOrg和SetWindowOrg函数来改变坐标原点的位置看下面两个例子: /* / 例子6-1 void CMyView:OnDraw(CDC * pDC) pDC-Rectangle(CRect(0,0,200,200);/全部采用默认画一个宽和高为200象素的方块 /* / 例子6-2 void CMyView:OnDraw(CDC * pDC) pDC-SetMapMode(MM_TEXT);/设定映射模式为MM_TEXT pDC-SetWindowOrg(CPoint(100,100);/设定逻辑坐标原点为(100,100) pDC-Rectangle(CRect(100,100,300,300);/画一个宽和高为200象素的方块 这两个例子显示出来的图形是一样的,都是从屏幕左上角开始的宽和高为200象素的方块,可以看出例子2将逻辑坐标(100,100)映射到了设备坐标(0,0)处,这样做有什么用?滚动窗口使用的就是这种变换。 固定比例映射模式: MM_LOENGLISH、MM_HIENGLISH、MM_LOMETRIC、MM_HIMETRIC、MM_TWIPS这一组是Windows提供的重要的固定比例映射模式。 它们都是x值向右方向递增,y值向下递减,并且无法改变。它们之间的区别在于比例因子见下:(我想书上P53页肯定是印错了,因为通过程序实验x值向右方向也是递增的) MM_LOENGLISH 0.01英寸 MM_HIENGLISH 0.001英寸 MM_LOMETRIC 0.1mm MM_HIMETRIC 0.01mm MM_TWIPS 1/1440英寸 /应用于打印机,一个twip相当于1/20磅,一磅又相当于1/72英寸。 看例3 /* / 例子6-3 void CMyView:OnDraw(CDC * pDC) pDC-SetMapMode(MM_HIMETRIC);/设定映射模式为MM_HIMETRIC pDC-Rectangle(CRect(0,0,4000,-4000);/画一个宽和高为4厘米的方块 还有一种是可变比例映射模式,MM_ISOTROPIC、MM_ANISOTROPIC。用这种映射模式可以做到当窗口大小发生变化时图形的大小也会相应的发生改变,同样当翻转某个轴的伸展方向时图象也会以另外一个轴为轴心进行翻转,并且我们还可以定义任意的比例因子,怎么样很有用吧。 MM_ISOTROPIC、MM_ANISOTROPIC两种映射模式的区别在于MM_ISOTROPIC模式下无论比例因子如何变化纵横比是1:1而M_ANISOTROPIC模式则可以纵横比独立变化。 让我们看例子4 /* / 例子6-4 void CMy002View:OnDraw(CDC* pDC) CRect rectClient; / GetClientRect(rectClient);/返回客户区矩形的大小 pDC-SetMapMode(MM_ANISOTROPIC);/设定映射模式为MM_ANISOTROPIC pDC-SetWindowExt(1000,1000); pDC-SetViewportExt (rectClient.right ,-rectClient.bottom ); /用SetWindowExt和SetViewportExt函数设定窗口为1000逻辑单位高和1000逻辑单位宽 pDC-SetViewportOrg(rectClient.right/2,rectClient.bottom/2 );/设定逻辑坐标原点为窗口中心 pDC-Ellipse(CRect(-500,-500,500,500);/画一个撑满窗口的椭圆。 / TODO: add draw code for native data here 怎么样,屏幕上有一个能跟随窗口大小改变而改变的椭圆。把 pDC-SetMapMode(MM_ANISOTROPIC);这句改为pDC-SetMapMode(MM_ISOTROPIC)会怎样?大家可以试试。那还有一个问题就是上例的比例因子是多少呢?看下面公式(注意是以例子4为例的) x比例因子=rectClient.right/1000 /视窗的宽除以窗口范围 y比例因子=-rectClient.bottom/1000 /视窗的高除以窗口范围 从Windows的鼠标消息可以获得鼠标指针的当前坐标值(point.x和point.y)此坐标值是设备坐标。 很多MFC库函数尤其是CRect的成员函数只能工作在设备坐标下。 还有我们有时需要利用物理坐标,物理坐标的概念就是现实世界的实际尺寸。 设备坐标-逻辑坐标-物理坐标之间如何进行转换便成为我们要考虑的一个问题,物理坐标和逻辑坐标是完全要我们自己来做的,但WINDOWS提供了函数来帮助我们转换逻辑坐标和设备坐标。 CDC的LPtoDP函数可以将逻辑坐标转换成设备坐标 CDC的DPtoLP函数可以将设备坐标转换成逻辑坐标 下面列出我们应该在什么时候使用什么样的坐标系一定要记住: CDC的所有成员函数都以逻辑坐标为参数 CWnd的所有成员函数都以设备坐标为参数 区域的定义采用设备坐标 所有的选中测试操作应考虑使用设备坐标。 需要长时间使用的值用逻辑坐标或物理坐标来保存。因设备坐标会因窗口的滚动变化而改变。 用书上的例子作为以前几篇的复习,如果你能够独立完成它说明前面的内容已经掌握。另外有些东西是新的,我会比较详细的做出说明,例如客户区、滚动窗口等。 第七篇:图形设备接口(GDI) 我想大家和我一样通过前几天的学习,对VC+MFC应用程序框架的神奇功能有了一些了解,但是还是感觉不能驾御这个强的开发工具,不过别担心,我170多斤体重不是一口吃出来的,是经过了30年不懈的努力才吃成了如此“魁梧”的体形,呵呵开个玩笑。所以学习也一样。学VC尤其如此。还有我发现很多好的技术类书籍有一个共同的特点,就是在前几章学到了一些东西在你正在疑惑或者苦苦领会的时候,接下来的章节便给你解除疑惑。雷神经验:遇到实在想不明白的地方先放下,继续向下读,也许读着读着前面的问题就明白了。VC+技术内幕当然属于好的技术书籍一类,所以在本书第五章开始仔细的给我们讲解设备环境类和图形设备接口(GDI),使得我们能守得云开见月明。设备环境类CDC: CDC是设备环境类的基类直接由CObject派生。是GDI的关键元素,它代表了物理设备。每一个C+设备环境对象都有相对应Windows设备环境,并通过一个32位类型的HDC句柄来标识。CDC类的虚拟性使我们可以很容易的做到编写同时适用于多种设备的代码。例如OnDraw函数的pDC-TextOut(0,0,Hello);既可以适用于显示器、还可以适用于打印预览和打印,只需要在CView:OnDraw函数的pDC参数指向不同的对象类。CClientDC和CWindowDC是显示设备环境类,都是由CDC派生而来,区别在于CClientDC是窗口的客户区不包括边框、标题栏和菜单栏,(0,0)指客户区域的左上角。CWindowDC的(0,0)指整个屏幕的左上角,这意味着我们可以在显示器的任意地方绘图,包括窗口边框、标题栏和菜单栏等等。CWindowDC一般应用在框架窗口,而不是视图窗口。CDC对象被创建后一定要在合适的时候将它删除掉,如果忘记了删除设备环境对象则会造成内存丢失。如何做才能避免出现这个问题呢,我们应该在堆栈中构造对象。看例子7-1/*/ 例子7-1void CMyView:OnLButtonDown(UINT nFlags,CPoint point)CRect rect;CClientDC dc(this); /在堆栈中构造设备环境对象,用一个窗口指针this作参数。dc.GetClipBox(rect); /GetClipBox函数是一个虚函数,作用是可以获得选定区域的尺寸/析构函数在函数返回时自动调用,也就完成对设备环境对象的删除。书上还给出了另一种写法:void CMyView:OnLButtonDown(UINT nFlags,CPoint point)CRect rect;CDC * pDC=GetDC(); /通过调用CWnd的GetDC()函数获得设备环境指针pDC-GetClipBox(rect); /可以获得选定区域的尺寸ReleaseDC(pDC); /一定不能忘记,释放设备环境。(书上又写错了) 创建的设备环境对象具有一些默认的特性,通过CDC类的成员函数可以设定这些特性。例如前一篇笔记用到的刷子、映射模式等等。我们还可以通过重载SelectObject函数将GDI对象选进设备环境中。GDI对象是通过CGdiObject派生类的C+对

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论