1 / 53

MFC 及其应用

MFC 及其应用. WINDOWS 应用程序一定要有 WinMain 函数,该函数用来完成一些特殊的任务, 象创建程序的主窗口,主窗口用来处理消 息的代码。. MFC 将 WinMain 隐藏在框架中,不象写 SDK 程序时可以很容易的找到它。. WINDOWS 采用的消息处理机制也交给了程序框架,我们不必担心如何使这些消息和代码联系起来 . WINDOWS 定义好了一些消息,当窗口被创建时系统就会发送 WM_CREATE 消息 . 当点击鼠标左键时便系统会发送 WM_LBUTTONDOWN 消息 当用户按下键盘时系统会发送 WM_CHAR 消息

Download Presentation

MFC 及其应用

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. MFC及其应用

  2. WINDOWS应用程序一定要有WinMain 函数,该函数用来完成一些特殊的任务, 象创建程序的主窗口,主窗口用来处理消 息的代码。 MFC将WinMain隐藏在框架中,不象写 SDK程序时可以很容易的找到它。

  3. WINDOWS采用的消息处理机制也交给了程序框架,我们不必担心如何使这些消息和代码联系起来 . • WINDOWS定义好了一些消息,当窗口被创建时系统就会发送WM_CREATE消息. • 当点击鼠标左键时便系统会发送WM_LBUTTONDOWN消息 • 当用户按下键盘时系统会发送WM_CHAR消息 • 当用户关闭窗口时系统会发送WM_CLOSE消息 • 当用户进行菜单项选择或单击按钮时系统回发送WM_COMMAND消息 • 什么都不做系统还会发送WM_TIMER消息

  4. WINDOWS提供通用的图形设备接口(GUI),我们通过调用(GDI)函数和硬件打交道,不必理会设备环境,WINDOWS会自动将设备环境结构映射到相应的物理设备,这就是设备无关性。 • 动态连接库(DLL)应该是代码重用的典型例子(不知道可不可这样说),把一些模块、自己新编的类单独调试并编译成DLL,及增加代码的可读性也提高了程序模块的灵活性。

  5. Developer Studio创建的相关中间文件 • APS -> 支持ResourceView • BSC -> 浏览器信息文件 • CLW -> 支持ClassWizard • DSP -> 项目文件,不能删除和 用文本编辑器编辑 • DSW -> 项目文件,不能删除和 用文本编辑器编辑

  6. Developer Studio创建的相关中间文件 • MAK -> 外部的创建文件 • NCB -> 支持ClassView • OPT -> 保存工作空间的配置 • PLG -> 建立日志文件 这些文件都有一定的作用,如CLW,如果你有 一个新类,需要加到ClassWizard中,除了将相 应的.h 和.cpp加到DSP中还需要重新编译CLW。 PLG文件记录着你的项目配置信息 …

  7. MFC特点 ◎MFC是C++的Microsoft Windows API,如果想要开发WINDOWS的应用程序当然VC/MFC是开发环境的首选。 ◎MFC产生的应用程序使用了标准化的 结构。 ◎MFC产生的应用程序短而运行速度快。 ◎VC++工具降低了编码的复杂性。 ◎MFC库功能非常丰富。

  8. 最简单的MFC例子”Hello,World” HELLO WORLD用AppWizard向导创建一个 显示一个字符串的单文档程序,只需要敲入一行 语句,完全体现了MFC的强大功能。 1、打开VC++6从菜单选择NEW,给项目命名为 ”MyApp01“。 2、选择MFC AppWizard[exe] 选项,除STEP 1选 择单文档外其他STEP缺省。

  9. 最简单的MFC例子”Hello,World” 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}

  10. 最简单的MFC例子”Hello,World” 在 // TODO: add draw code for native data here的位置增加一行代码 void CMyApp01View::OnDraw(CDC* pDC){CMyApp01Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);pDC->TextOut(10,10," Hello,World");  //增加的一行// TODO: add draw code for native data here}

  11. MFC程序中的元素 ①WinMain函数:并非不存在只是已经被隐藏 在应用程序框架内部。 ②CMyApp类:CMyApp类的对象代表一个应用 程序,CWinApp基类决定它的大部分行为。 ③应用程序的启动:当开始运行应用程序时 WINDOWS会调用WinMain函数,WinMain会 查找该应用程序的全局对象theApp。 ④CMyApp::InitInstance成员函数: 发现theApp后自动调用重载的虚函数 InitInstance来完成主窗口的构造和显示工作。

  12. MFC程序中的元素 ⑤CWinApp::Run成员函数:WinMain在调用 InitInstance之后紧接着调用Run函数,它被 隐藏在基类中负责传递应用程序的消息给相 映的窗口。 ⑥CMyFrame类:此类的对象代表着应用程序 的主窗口。它的构造函数调用基类CFrameWnd 的Create函数创建具体的窗口结构。 ⑦CMyFrame::OnLButtonDown函数:演示消息 处理机制,当鼠标坐键被按下这一事件被映射 到CMyFrame的OnLButtonDown函数上,如果 你选择F5进行编译运行的话可以在调试窗口看 到TRACE宏显示的信息

  13. MFC程序中的元素 ⑧CMyFrame::OnPaint函数:应用程序每次重新 绘制窗口都需要调用此函数,将显示 “Hello World!”放在这里是因为每次窗口发生变化 时保证"Hello World!"被显示,你可以试着将语句: CPaintDC dc(this);dc.TextOut (0,0,"Hello World!");写在别出,例如写在void CMyFrame::OnLButtonDown (UINT nFlags,CPoint point){TRACE("Entering CMyFrame::OnLButtonDown - %lx,%d,%d\n",(long)nFlags,point.x ,point.y);CPaintDC dc(this);dc.TextOut (0,0,"Hello World!");}

  14. MFC程序中的元素 运行后当点击左键时显示“Hello World!”, 但当窗口最小化再最大化时"Hello World!"不见了。 ⑨关闭应用程序:用户关闭应用程序时会有一 系列事件发生。首先CMyFrame对象被删除, 然后退出Run,进而退出WinMain,最后 删除CMyApp对象。 上面的示例可见程序的大部分功能包含在基类CWinApp和CFrameWnd中,我们只写了很少的函数,便可以完成很复杂的功能。所以应用程序框架不仅仅是一种类库,它还定义了应用程序的结构,除了基类外还包括WinMain函数,以及用来支持消息处理、诊断、DLL、等都包含在应用程序框架中。

  15. MFC的消息映射 MFC是通过一些宏来将特定的消息影射到派生类 相应的成员函数上,这种体制的好处是允许某些 非窗口类(如文档类)来控制命令消息。 且不需要C++作任何扩展。 MFC的消息控制函数要求提供函数原形、函数体 以及消息映射中的入口。 用Class Wizard可以很容易的将上面内容加到 类中。例如只要在Class Wizard中添加 WM_LBUTTONDOWN消息,则相应的代码 便加在合适的地方。

  16. MFC的消息映射 应用程序除了包含应用程序框架类外,一般 还要包含文档和视图类。 这种文档-视图结构是应用框架的核心。 文档好比后台的数据库,视图就是界面上显示 的内容,同一个数据库可以用不同的界面显示, 但由于所有的界面内容都是从数据库中数据得来 ,所以当数据库发生变化时所有的相关界面显示 都会跟着改变。 应用程序实际上就是通过视图对文档进行一系 列操作。

  17. MFC 视图 视图是一个从CView类派生的类的对象, 在屏幕上显示的窗口就是一种。 对象的行为完全由类的成员函数和数据成员 决定,其中及包括派生类中的特定函数,也 包括基类的标准函数,所以有必要了解MFC 类库的结构以及各类的标准成员函数 。 我们来回顾前面例子项目程序所在目录下 的相关文件:

  18. MFC 视图 myapp01.dsp ---项目文件 myapp01.dsw ---工作空间文件 myapp01.rc  ---资源描述文件 myapp01View.cpp ---包含CMyAppView 类成员函数的视图类实现文件 myapp01View.h ---包含CMyAppView 类成员函数的视图类头文件 myapp01.opt ---二进制文件,告诉 Developer Studio本项目的哪些文件是打开 的,又是如何排列的

  19. MFC 视图 readme.txt ---用来解释所产生的所有文件, 未列出的myapp01Doc.cpp、myapp01Doc.h、 StdAfx.cpp、StdAfx.h....在这里都可以找到 相应解释。 resource.h ---包含#define常量定义的头文件 CMyAppView类的OnDraw成员函数,它是虚函数, 作用是每当窗口需重绘时应用程序框架会调用它。

  20. MFC 视图 在myapp01View.h可以找到OnDraw原型 : virtual void OnDraw(CDC* pDC); // overridden to draw this view 参数是CDC类的指针,WINDOWS是通过和 窗口相关联的设备环境(CDC类的对象就是 设备环境)和显示硬件进行通讯。 有了这个指针我们便可以调用CDC类的成员 函数来完成各种绘制工作 。 如前面用到的TextOut(),还有一些如Ellipse()、 Polygon()、BitBlt()等 。

  21. MFC 资源文件 资源文件(就是以应用程序名和扩展名是.rc 的文件)很大程度上决定了应用程序的用户界面。 在VC++中资源文件包括以下内容: Accelerator --->模拟菜单和工具栏的选择内容 Dialog --->对话框的布局及内容 Icon ---> 图标有两种一种是16X16一种是32X32 Menu---> 应用程序的主菜单及所属的弹出式菜单 String table --->字符串不属于C++源代码部分 Toolbar --->工具条 Version --->程序的描述、版本号、支持语言信息

  22. MFC 资源文件 以上信息都在.rc文件中包含,同时.rc文件 还包含了以下语句: #include “afxres.h”#include “afxres.rc”它们的作用是把适合于所有应用程序的一些通用MFC库资源包含进来。 需要注意的是虽然resource.h是一个ASCII码文件 可以用文本编辑器进行编辑,但如果使用文本编 辑器进行编辑的话,下次再使用资源编辑器时所 做的修改有可能丢失,所以我们应该在尽量在资 源编辑器中编辑应用程序的资源,新增的资源内 容会自动地添加在我们的程序相应位置。

  23. MFC编译模式 在VC++中有两种编译模式,一种是Release Build另一种是Debug Build。 它们之间的区别在于,Release Build不对源 代码进行调试,不考虑MFC的诊断宏,使用 的是MFC Release库,编译十对应用程序的 速度进行优化,而Debug Build则正好相反, 它允许对源代码进行调试,可以定义和使用 MFC的诊断宏,采用MFC Debug库,对速度 没有优化。

  24. MFC编译模式 所以我们应该在Debug模式下开发应用程序, 然后在Release模式下发布应用程序。在我们 的工程文件夹下会有一个Debug文件夹和一个 Release文件夹分别存放输出文件和中间文件。 诊断宏是我们编译程序时检测程序状态的有利 工具,利用TRACE宏,可以在Debug窗口获得 你需要的诊断信息,而不用设置对话框之类的 方法,在发布时Release会自动滤掉此信息。 有了VC++提供的调试工具如诊断宏、设断点、 单步执行等等,会让我们省不少力气。

  25. MFC基本事件处理 我们已经知道MFC库应用程序框架调用CView 视图类的虚函数OnDraw来完成屏幕显示。 其实CView和CWnd类包含了几百个成员函数, 在MSDN中可以看到这些成员函数, 其中有许多On开头的,前面的例子就有一个 OnLButtonDown,它们都是应用程序框架响 应各种事件所需调用的函数。 OnDraw便是当窗口发生变化是被调用的, OnLButtonDown是鼠标左键被按下时调用, 还有OnKeyDown是键盘被按下时调用等等。

  26. MFC基本事件处理 当用户在视窗中按下鼠标左键时,Windows会 自动发送WM_LBUTTONDOWN消息给该视窗, 当然你可以什么都不做,如果你想要让程序对 此消息做出反应就必须在视图类给出相应的函数, 类似下面这样: void CMyView::OnLButtonDown(UINT nFlags,CPoint point){//做些事情的代码} 还需要在类头文件包含相应的函数原型说明afx_msg void OnLButtonDown(UINT nFlags,CPoint point);afx_msg只是说明该函数原型是针对消息映射函数。

  27. MFC基本事件处理 下一步在代码文件中还需要有一个消息映射宏, 作用是把OnLButtonDown函数和应用程序框架 联系在一起。BEGIN_MESSAGE_MAP(CMyView,CView)ON_WM_LBUTTONDOWNEND_MESSAGE_MAP() 最后在类库的头文件还需包含:DECLARE_MESSAGE_MAP() 函数和Windows消息的对应关系可以从MSDN中 找到在MSDN中索引输入(WM_ Messages) 便会列出所有的Windows消息和消息控制函数原型。

  28. MFC基本事件处理 在实际的编程过程中我们不可能全部都用手工 的添加或编制消息控制函数。除了一些特殊的, 我们一般是借助Class Wizard来自动编制消息 映射函数。这又是MFC应用程序框架比起SDK 来的有一个便捷的地方。 MFC库对140种windows消息直接提供了消息控 制函数,并且我们还可以自己定义自己的消息。 下面列出的几种消息是我们应该特别注意的: (MSDN上有更详细的内容)

  29. MFC基本事件处理 WM_CREATE 该消息是Windows发给视图的第一个消息。 当应用程序框架调用create函数时该消息便 会被发送,此时窗口还未创建完成,不可见, 因此在消息控制函数OnCreate内不能调用那些 依赖窗口处于完全激活状态的Windows函数。 如果需要可以在重载的OnInitialUpdate函数内 调用。不过注意在SDI应用程序OnInitialUpdate 函数可能被多次调用。

  30. MFC基本事件处理 WM_CLOSE 当用户关闭窗口时,系统会发送WM_CLOSE消息。 如果派生类重新定义了OnClose函数,就可以完全 控制关闭过程,可以将提醒用户存盘之类的工作 放在这里完成。 WM_QUERYENDSESSION 从字面的意思看就可以看出,当用户退出 Windows时,或者调用了ExitWindows 函数时。 Windows会发送WM_QUERYENDSESSION消息 给所有的正在运行的应用程序,由 OnQueryEndSession消息映射函数对消息进行处理。 在它之后应该是WM_ENDSESSION 消息。

  31. MFC基本事件处理 WM_DESTROY 在Windows发送WM_CLOSE消息后,紧接着会 发送WM_DESTROY消息,虽然窗口已经Close 但实际上并没有完全清除,在任务管理器中还 可以看见应用程序的进程(我想很多木马或病毒 都是无窗口的程序,它们的做法是生成了已经活动 状态的窗口但不显示出来),利用这个消息控制 函数便可以对依赖于当前窗口存在的东西做清除 工作,不过一定要注意,应该调用基类的 OnDestroy函数,而不能在用户自己的视图的 OnDestroy函数中终止窗口的析构过程,终止 析构过程应该在OnClose函数中。

  32. MFC映射模式 在窗口显示图形,更准确的说是在窗口指定位置 显示图形或文字,我们使用的坐标单位是象素, 称之为设备坐标。 pDC->Rectangle(CRect(0,0,200,200)); 画一个高和宽均为200个象素的方块,因为采用 的是默认的MM_TEXT映射模式,所以在设备环境 不一样时,画的方块大小也不一样,在1024*768 的显示器上看到的方块会比640*480的显示器上 的小(在不同分辨率下的屏幕象素), 在输出到打印机时也会有类似的情况发生。

  33. MFC映射模式 如何做才能保证在不同设备上得到大小一致的 方块或者图形、文字呢? 需要进行模式映射选择,来转换设备坐标 和逻辑坐标。 Windows提供了以下几种映射模式: MM_TEXTMM_LOENGLISHMM_HIENGLISHMM_LOMETRICMM_HIMETRICMM_TWIPSMM_ISOTROPICMM_ANISOTROPIC

  34. MFC映射模式 MM_TEXT 默认的映射模式,把设备坐标被映射到象素。 x值向右方向递增;y值向下方向递增。 坐标原点是屏幕左上角(0,0)。 可以通过调用CDC的SetViewprotOrg和 SetWindowOrg函数来改变坐标原点的位置。 void CMyView::OnDraw(CDC * pDC){      pDC->Rectangle(CRect(0,0,200,200)); //全部采用默认画一个宽和高为200象素的方块}

  35. MFC映射模式 void CMyView::OnDraw(CDC * pDC){      pDC->SetMapMode(MM_TEXT); //设定映射模式为MM_TEXT      pDC->SetWindowOrg(CPoint(100,100)); //设定逻辑坐标原点为(100,100)pDC->Rectangle(CRect(0,0,200,200));//*** //画一个宽和高为200象素的方块} 这两个例子显示出来的图形是否一样 ? pDC->Rectangle(CRect(100,100,300,300)); //***改成上句哪?

  36. MFC映射模式 固定比例映射模式: MM_LOENGLISH、MM_HIENGLISH、 MM_LOMETRIC、MM_HIMETRIC、MM_TWIPS 是Windows提供的重要的固定比例映射模式。 它们都是x值向右方向递增,y值向下递减。 它们之间的区别在于比例因子:MM_LOENGLISH 0.01英寸MM_HIENGLISH 0.001英寸MM_LOMETRIC 0.1mmMM_HIMETRIC 0.01mmMM_TWIPS 1/1440英寸 //应用于打印机,一个twip相当于1/20磅,一磅又相当于1/72英寸。

  37. MFC映射模式 void CMyView::OnDraw(CDC * pDC){    pDC->SetMapMode(MM_HIMETRIC); //设定映射模式为MM_HIMETRIC    pDC->Rectangle(CRect(0,0,4000,-4000)); //画一个宽和高为4厘米的方块} 还有一种是可变比例映射模式, MM_ISOTROPIC、MM_ANISOTROPIC。

  38. MFC映射模式 用这种映射模式可以做到当窗口大小发生变化 时图形的大小也会相应的发生改变,同样当翻 转某个轴的伸展方向时图象也会以另外一个轴 为轴心进行翻转,并且我们还可以定义任意的 比例因子。 MM_ISOTROPIC、MM_ANISOTROPIC两种映射 模式的区别在于MM_ISOTROPIC模式下无论比 例因子如何变化纵横比是1:1而 M_ANISOTROPIC模式则可以纵横比独立变化。

  39. MFC映射模式 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}

  40. MFC映射模式 怎么样,屏幕上有一个能跟随窗口大小改变 而改变的椭圆。 把pDC->SetMapMode(MM_ANISOTROPIC); 这句改为pDC->SetMapMode(MM_ISOTROPIC) 会怎样?大家可以试试。那还有一个问题就是 上例的比例因子是多少呢?x比例因子=rectClient.right/1000 //视窗的宽除以窗口范围y比例因子=-rectClient.bottom/1000 //视窗的高除以窗口范围

  41. MFC映射模式 我们有时需要利用物理坐标,物理坐标的概念 就是现实世界的实际尺寸。 设备坐标-逻辑坐标-物理坐标之间如何进行转换 便成为我们要考虑的一个问题,物理坐标和逻辑 坐标是完全要我们自己来做的,但WINDOWS 提供了函数来帮助我们转换逻辑坐标和设备坐标。 CDC的LPtoDP函数可以将逻辑坐标 转换成设备坐标 CDC的DPtoLP函数可以将设备坐标 转换成逻辑坐标

  42. MFC映射模式 下面列出我们应该在什么时候使用什么样 的坐标系一定要记住: ◎CDC的所有成员函数都以逻辑坐标为参数 ◎CWnd的所有成员函数都以设备坐标为参数 ◎区域的定义采用设备坐标 ◎所有的选中测试操作应考虑使用设备坐标 ◎需要长时间使用的值用逻辑坐标或物理坐标 来保存。 因设备坐标会因窗口的滚动变化而改变。

  43. 图形设备接口(GDI) 设备环境类CDC CDC是设备环境类的基类直接由CObject派生。 是GDI的关键元素,它代表了物理设备。 每一个C++设备环境对象都有相对应Windows 设备环境,并通过一个32位类型的HDC句柄 来标识。 CDC类的虚拟性使我们可以很容易的做到编写 同时适用于多种设备的代码。 如OnDraw函数的pDC->TextOut(0,0,"Hello"); 既可以适用于显示器、还可以适用于打印预览 和打印,只需要在CView::OnDraw函数的pDC 参数指向不同的对象类。

  44. 图形设备接口(GDI) CClientDC和CWindowDC是显示设备环境类, 都是由CDC派生而来,区别在于CClientDC是 窗口的客户区不包括边框、标题栏和菜单栏, (0,0)指客户区域的左上角。 CWindowDC的(0,0)指整个屏幕的左上角, 这意味着我们可以在显示器的任意地方绘图, 包括窗口边框、标题栏和菜单栏等等。 CWindowDC一般应用在框架窗口,而不是 视图窗口。

  45. 图形设备接口(GDI) 创建的设备环境对象具有一些默认的特性, 通过CDC类的成员函数可以设定这些特性。 例如刷子、映射模式等等。我们可以通过重载 SelectObject函数将GDI对象选进设备环境中。 GDI对象是通过CGdiObject派生类的C++对象 来表示的。 CBrush是一个GDI的派生类,它在MFC中的层次 结构是这样的:CObject派生CGdiObject派生 CBrush。CGdiObject是所有GDI对象的抽象基类。

  46. 图形设备接口(GDI) 下面列出的是GDI派生类的列表: CBitmap:位图是一种位矩阵,每一个显示象素 都对应于其中的一个或多个位,可以用来表示 图象,也可以用来创建刷子 CBrush:刷子定义了一种位图形式的象素, 可以用来对区域内部填充颜色。 CFont:字体是一种具有某种风格和尺寸的所有 字符的完整集合,常常被作为资源,其中一些 依赖某种设备。

  47. 图形设备接口(GDI) CPalette:调色板是一种颜色映射接口,它允许 应用程序在不影响其他应用程序的前提下,可 以充分利用输出设备的颜色描绘能力。 CPen:笔是一种用来画线及绘制有形边框的 工具,可以指定它的颜色及宽度,并可以指定 画虚线、点线还是实线。 CRgn:区域是由多边形、椭圆二者组合形成的 一种范围,可以用来进行填充、裁剪、鼠标点 中测试等等。

  48. 图形设备接口(GDI) CGdiObject类很眼生,看过很多代码就没有看 到过它,原因是由于CGdiObject类是所有GDI 对象类的虚拟基类,所以我们不必创建 CGdiObject类的对象,可以直接构造它的派生 类的对象,例如 : CPen newPen(PS_DASHDOTDOT,2,(COLORREF) 0); //黑色的笔宽度为2 但需要注意的是CFont和CRgn的对象建立需要 先调用默认的构造函数来构造C++对象,然后 再调用相应的创建函数如:CreateFont或CreatePolygonRgn等。

  49. 图形设备接口(GDI) CGdiObject类有一个虚拟的析构函数,它派生类 的析构函数需要将与C++对象相关联的GDI对象 删除掉,一定要在退出程序之前把构造的 CGdiObject派生类对象释放掉。因为一个没有 释放的GDI对象会占用很多的内存。

  50. 图形设备接口(GDI) void CMy10View::OnDraw(CDC* pDC){pDC->MoveTo (10,10);pDC->LineTo (110,10);CPen newPen(PS_DASHDOTDOT,10,(COLORREF) 192); //红色的笔宽度为10CPen * pOldPen=pDC->SelectObject (&newPen); //在将新对象选进设备环境的同时返回指向前一次被选 对象的指针。作用保存原来的对象,以便完成任务时恢复它。pDC->MoveTo (10,20);pDC->LineTo (110,20);pDC->SelectObject (pOldPen);//把原来的对象恢复pDC->MoveTo (10,30);pDC->LineTo (110,30);}

More Related