1 / 48

VC++ 程序设计

VC++ 程序设计. 1 设备环境. Windows 使用一个称为设备环境 (DeviceContext) 的对象的方法 — 但该对象的创建没有一个 C++ 类,因为 Windows 早于并存在于 C++ 之外。 设备环境对象用一些默认值创建,可以用它们创建默认的设备环境。 应用 Windows 绘制一直线,所需的是一个设备环境对象的指针和直线坐标,设备环境对象的指针叫做设备环境句柄 (HDC) 。 ::MoveTo(HDC hdc, int x, int y); ::LineTo(HDC hdc, int x, int y);.

yaakov
Download Presentation

VC++ 程序设计

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. VC++程序设计

  2. 1设备环境 • Windows使用一个称为设备环境(DeviceContext)的对象的方法—但该对象的创建没有一个C++类,因为Windows早于并存在于C++之外。 • 设备环境对象用一些默认值创建,可以用它们创建默认的设备环境。 • 应用Windows绘制一直线,所需的是一个设备环境对象的指针和直线坐标,设备环境对象的指针叫做设备环境句柄(HDC)。 • ::MoveTo(HDC hdc, int x, int y); • ::LineTo(HDC hdc, int x, int y);

  3. 要绘制一个完整的形状,::MoveTo()函数只被调用一次。然后,::LineTo()函数被调用要绘制一个完整的形状,::MoveTo()函数只被调用一次。然后,::LineTo()函数被调用 • 设备无关 • 设备环境是设备无关的,它允许你编写软件而不必指定一个设备。这些软件必须知道的是:它是编写一个设备环境的,而不管该设备环境是屏幕还是Epson打印机。之后,设备环境可以被分配给一个打印机、屏幕、位图或一个文件。

  4. 2、在MFC环境中创建一个设备环境 • MFC用CDC类封装了一个设备环境对象,CDC的成员变量m_hdc指向它所拥有的设备环境,用户可以创建四种类型的设备环境 • 屏幕 • 打印机 • 内存 • 位图

  5. 2.1 屏 幕 • 创建一个屏幕设备环境,可以用: • CDC*pDC=GetDC(); • 这里的GetDC()是CWnd类的成员函数,它返回一个允许用户绘制它的窗口客户区的设备环境; • 如果还希望绘制非客户区,则使用: • CDC*pDC=GetWindowDC(); • 如果需要绘制整个屏幕 • CDC*pDC=CDC::FromHandle(::GetDC(NULL));

  6. 必须保证在用完设备环境后释放它,否则系统将发生冲突并导致异常终止。虽然设备环境是被创建的,但内存资源还是有限的必须保证在用完设备环境后释放它,否则系统将发生冲突并导致异常终止。虽然设备环境是被创建的,但内存资源还是有限的 • ReleaseDC(pDC); • 用户最有可能用通用设备环境来做绘图工作。每次释放一个通用设备环境时,为它们设置的值都被丢失。但是,可以用下面两个CDC成员函数保存和恢复一个设备环境的设置值: • SaveDC()保存设备环境的当前状态。 • RestoreDC()将设备环境恢复到用SaveDC()保存的状态。

  7. 2.2 打印机 • 要为打印机创建一个设备环境,必须先创建一个CDC类对象,然后使用它的CreateDC() • CDC dc; • dc.CreateDC(LPCTSTR lpszDriverName, LPCTSTR lpszDeviceName, LPCTSTR lpszOutput, Const void * lpInitData)

  8. 使用打印机设备环境之后,必须用CDC类的DeleteDC()成员函数销毁它。但是,若在堆栈中创建CDC类,则程序返回时,设备环境自动被删除。使用打印机设备环境之后,必须用CDC类的DeleteDC()成员函数销毁它。但是,若在堆栈中创建CDC类,则程序返回时,设备环境自动被删除。 • CMyClass::Drawing(.) { CDC dc; dc.CreateDC(.); }

  9. 2.3 内 存 • 要创建一个可以直接绘制位图的设备环境,必须先用CDC的CreateCompatibleDC()成员 • 函数创建一个CDC类对象。 CDC dc; dc.CreateCompatibleDC(HDC hdc); • CreateCompatibleDC()用设备环境的设置值初始化它所创建的设备环境对象,因此,取名兼容DC。应该从显示被创建的位图的设备(如屏幕、打印机)传递一个设备环境。

  10. 要真实地绘制一个位图,还必须创建一个空位图对象,并使该设备环境与该位图相关联。要真实地绘制一个位图,还必须创建一个空位图对象,并使该设备环境与该位图相关联。 • CDC dc; //create CD Cobject CBitmap bitmap; //create CBitmap object dc.CreateCompatibleDC(pDC);// bitmap.CreateCompatibleBitmap(pDC,ICON_WIDTH,ICON_HEIGHT); dc.SelectObject(&bitmap); //to this bitmap • 绘制位图以后,必须用下列语句删除设备环境: • dc.DeleteDC();

  11. 3绘图例程 • CDC类还在它的成员函数中封装了全部Windows图形API,这些成员函数包括: • 画点的函数。 • 画线的函数。 • 画形状的函数。 • 填充和翻转形状的函数。 • 滚动屏幕的函数。 • 绘制文本的函数。 • 绘制位图和图标的函数

  12. 3.1画点 • 像素点的绘制不过是改变单个像素点的颜色。 • SetPixel()试图用指定的颜色画一个像素,返回绘制时使用的实际颜色 • SetPixelV()与上面的基本相同,但不用返回绘制时使用的实际颜色,因而速度更快

  13. 3.2画线 • 画线即改变屏幕上一系列像素点的颜色。 • MoveTo()开始画线、弧和多边形时,把光标移动到一个初始位置 • LineTo()画一条从初始位置到另一个点的直线 • Arc()画一段弧 • ArcTo()画一段弧,并更新初始位置 • AngleArc()画一条线,然后画一段弧,并更新初始位置 • PolyDraw()画一系列线段和Bezier样条 • PolyLine()画一系列线段 • PolyPolyLine()画多个系列线条

  14. 3.3画形状 • 这里的形状是一系列封闭线条。 • Rectangle()画一个矩形 • Pie()画一个饼状楔形 • RoundRect()画一个圆角矩形 • Draw3dRect()画一个三维矩形 • Polygon()画一个多边形 • DrawEdge()画一个矩形的边缘 • PolyPolygon()创建一个或多个多边形DrawFrameControl()画一个框架控件 • Ellipse()画一个椭圆

  15. 3.4形状填充和翻转 • 填充和翻转改变一个形状内的所有像素点颜色。 • FillRect()填充一个矩形 • FillSolidRect()用用一单色填充一个矩形 • InvertRect()反转一个矩形的颜色 • ExtFloodFill()用用当前画刷填充一个区域,提供比FloodFill()成员函数更多的灵活性 • FrameRect()画一个矩形的边框

  16. 3.5滚动 • 通过滚动,可移动屏幕周围像素颜色。 • ScrollDC()左、右、上、下移动屏幕图像。

  17. 3.6绘制文本 • 我们可能会认为文本是打印的,不是画的;但在一个图形用户界面中,甚至一个文本字符都是由像素构成的一幅图。 • TextOut()在在一个指定的位置,输出一个字符串 • ExtTextOut()在在一个矩形区域里输出一个字符串 • TabbedTextOut()在基于用该函数传输的一个表,在指定位置输出一个字符串,并将字符串中的任何制表符转换为空格 • DrawText()在在指定的矩形域里绘制文本,但比TextOut()有更多的选项,如把文本居中和显示多行文本

  18. 3.7绘制位图和图标 • 一个位图或图标只是大量像素的颜色阵列。通常有一个标题,用来指示在一行中有多少像素点,以便一个画图例程知道什么时候开始下一行。通常,位图绘制例程只是把像素阵列拷贝到视频内存中。图标具有透明色这一附加的能力,换句话说,当一个图标被绘制在屏幕上时,它的每一点的颜色都可被屏幕上原有的颜色代替。 • DrawIcon()在在指定的位置画一个图标 • BitBlt()在从指定的设备环境中拷贝一个位图,通常是从磁盘中装入或在内存中创建, • StretchBlt()在与BitBlt()基本相同,但它试图伸展或压缩一个位图以适应目标 • PatBlt()在创建一个位模式

  19. 4 绘图属性 • 因为所有的绘图函数只有一个设备环境,因此,每个函数可能只使用存储在设备环境中20%的属性。 • 一个设备环境既可以自身包含一种特定的绘图属性,也可以指向另一个包含某种特定属性的对象。例如,画一条线的属性(如宽度或颜色)可存储在一个单独的Pen对象中,而由设备环境指向该对象。 • 创建这些附加的图形对象,与创建一个窗口对象的方法一样,先创建MFC类对象,然后调用那个类的成员函数Create()。附加的图形对象一旦被创建,需要告诉设备环境运用SelectObject()使用该新对象,SelectObject()只是把设备环境指向新的图形对象。

  20. CPen pen; pen.CreatePen(.); CPen*pOldPen=dc.SelectObject(&pen); • 用新对象绘图后,必须从内存中删除该对象。因为设备环境仍指向该对象,所以,必须先把它指向另一个对象—通常是原先的对象。 • dc.SelectObject(pOldPen); • pen.DeleteObject()

  21. 7 控制什么时候在哪里绘图 • 通常,当处理一个WM_PAINT或WM_DRAWITEM窗口消息时,应当在窗口中绘制。当绘制窗口客户区的时候,由系统发送WM_PAINT窗口消息;当需绘制控件的某部分时,WM_DRAWITEM消息被发送到用户绘制控件的物主窗口。 • 也可以在其他时间画,但必须注意,下一次处理WM_PAINT消息时,无论画什么都将被绘图过程所覆盖。要想再在窗口绘图,只能作为鼠标命令的结果移动对象或线条,例如,在视图中,用鼠标绘制一个套索框框选取一组目标。 • 注意可以用CWnd::LockWindowUpdate()停止绘图过程绘制窗口。然而,这时该窗口就不能被移动了。

  22. 7.1处理WM_PAINT • 处理WM_PAINT消息的标准方法是: Void CMyWnd::OnPaint() { //creates a Device Contextdraw to dc CPaintDC dc(this); ::: } • 这里看到的CPaintDC类是CDC类的派生类。它不仅创建一个设备环境,而且在OnPaint()返回和CPaintDC析构自己时销毁该设备环境

  23. 7.2只绘制被无效化的区域 • 为了防止过度的屏幕闪烁并加快刷新速度,从CPaintDC获得的设备环境不总是允许绘制一个窗口的整个客户区,而只允许重画窗口中发生变化的部分(如一个文本文档的最后一行)。CPaintDC通知设备环境剪切掉在无效区域以外的任何绘图,这可以通过把被无效化的区域添加到设备环境的Region对象中实现;如果再调用,则Region对象定义一个剪切区域,在该区域以外不能进行绘制。 • InvalidateRect(rect); • Invalidate(); • UpdateWindow();

  24. OnDraw() • 当对一个视图(用CView类或它的派生类创建的窗口)进行绘制时,应当在CView的OnDraw()函数中处理WM_PAINT消息,而不是在它的OnPaint()中。通过一个打印机设备环境调用OnDraw(),CView可以把视图打印到打印机上。当用户使用File菜单中的标准Print命令时,就是这样实现的。 • 但是,许多应用程序不执行OnDraw(),因为它们不直接使用CView;一些使用CFormView类创建的视图由通用控件组成,而通用控件不用OnDraw()画它们自己,但还是可以打印这种类型的视图,不过此时可进行屏幕捕捉而不能绘图

  25. 7.3在其他时间绘图 • 你可能在鼠标命令之后绘图,例如,当用鼠标来绘制一条直线时。 • 还可以使用另外两个CDC类的派生类,它们可以使工作轻松。CClientDC()类像CPaintDC()一样创建一个设备环境,但它不试图剪裁任何东西。当过程开始时,CClientDC类创建设备环境;而当过程结束时,释放它。 • CMyClass::Foo() { CClientDC dc(this); ::: }

  26. 注意在使用设备环境带来方便的同时,也可能会带来隐患。其中之一就是必须记住在使用之后必须释放它们,否则将承受应用程序慢慢使用完内存的痛苦。不用CDC*pDC=GetDC(),而养成使用CClientDC的习惯,可能会得到更好的服务,因为不必考虑释放设备环境。注意在使用设备环境带来方便的同时,也可能会带来隐患。其中之一就是必须记住在使用之后必须释放它们,否则将承受应用程序慢慢使用完内存的痛苦。不用CDC*pDC=GetDC(),而养成使用CClientDC的习惯,可能会得到更好的服务,因为不必考虑释放设备环境。 • CWindowDC()类与CClientDC()的目的相同,但是,它创建的设备环境允许对整个窗口进行绘制,其中包括非客户区。

  27. 例1 绘制图形 • 1.创建一个设备环境 • 1)如果处理一个WM_PAINT消息或其他类似的消息,则可以提供一个设备环境,如果没有提供,则必须自己创建一个;如果要绘制一个屏幕,可以用下面的代码创建一个设备环境,这里的pWnd是CWnd类的实例的指针。该类的实例应该拥有需要绘制的窗口。 • CDC*pDC=pWnd->GetDC(); • 2)如果创建一个自己的设备环境,用完后必须销毁它;否则,会发生另一种内存泄漏,称为资源泄漏。销毁一个设备环境,用: • pWnd->ReleaseDC(pDC);

  28. 2.创建一个画笔 1)根据画线所需的特征创建CPen类的一个实例。 CPen pen( PS_SOLID, //solid line also //PS_DASH,PS_DOT,PS_DASHDOT, //PS_DASHDOTDOT //PS_NULL 2, //width in pixels RGB(128,128,128)); //color

  29. 2)让设备环境指向该新画笔对象,但还要保存一个旧画笔的指针,以便以后能恢复它。2)让设备环境指向该新画笔对象,但还要保存一个旧画笔的指针,以便以后能恢复它。 • Cpen*pPen=pDC->SelectObject(&pen); • 另一个在设备环境中预定义的特征是填充色(用来绘制封闭图形内部的颜色),它与一个绘制封闭图形的函数一起使用;默认的颜色是白色,但通过告知设备环境使用一个新的画刷对象,可以改变填充颜色。

  30. 3.创建一个画刷 1)用需要的颜色创建CBrush类的一个实例。 CBrush brush(RGB(128,128,128)); 2)让设备环境指向该新画刷对象,但还要保存旧对象的指针,以便以后能恢复它。 CBrush*pBrush= pDC->SelectObject(&brush);

  31. 4.用CDC类成员函数绘制图形 • 1)用该设备环境画一条直线,用: pDC->MoveTo(5,5); pDC->LineTo(25,25); • 2)绘制一个矩形,用: pDC->Rectangle(CRect(5,55,50,85)); • 3)绘制弧,用: pDC->Arc(CRect(5,115,50,145), CPoint(5,115), CPoint(50,115));

  32. 4)绘制圆角矩形,用: pDC->RoundRect(CRect(5,185,50,215), CPoint(15,15)); //distance from corner to draw arc 5)绘制椭圆或圆,用: pDC->Ellipse(CRect(250,5,305,25)); 6)绘制饼图,用: pDC->Pie(CRect(250,55,305,85) CPoint(250,55), //starting point CPoint(305,55)); //end point

  33. 例2 绘制文本 • 如果不存在设备环境,则用前面例子中介绍的技术创建一个。一种常见的方法如下: • CDC*pDC=pWnd->GetDC(); • 1.使用TextOut() • 1)绘制一个文本串,用: • CString str("Thisisdrawntext"); pDC->TextOut(x,y,str,str.getLength());

  34. x和y变量定义文本位置的左上角,如果要x和y指示别的位置,如文本的中心位置,可以用CDC::SetTextAlign()改变x和y的含义。x和y变量定义文本位置的左上角,如果要x和y指示别的位置,如文本的中心位置,可以用CDC::SetTextAlign()改变x和y的含义。 • 2)使x和y代表文本中央位置,在调用TextOut()之前调用下面的函数: • pDC->SetTextAlign(TA_CENTER);) • 也可以用下面的函数,改变y对齐方式: • pDC->SetTextAlign(TA_BOTTOM);) • 3)用不同的标准字形绘制文本,在绘制前使用下面的函数调用(参见MFC文档有关他库存字体): • pDC->SelectStockObject(ANSI_VAR_FONT);

  35. 4)创建绘制文本的字体,可以用: • CFontfont; • font.CreateFont(-22,0,0,0,FW_NORMAL, 0, 0, 0, 0,0,0,0,0,"Courier"); • CFont*pFont=(CFont*)pDC->SelectObject(&font); • CreateFont()不是真正地创建一种字体,相反它扫描系统当前安装的字体,寻找一种与用户调用参数中指定的标准最匹配的字体,并使用这种字体。

  36. 5)改变窗口的默认字体,可以用: • pwnd->SetFont(pFont);//thefont • 默认字体被自动地选进从那个窗口创建的任一设备环境中。 • 6)改变文本的颜色,用: • pDC->SetTextColor(RGB(100,100,100)); • 7)改变文本的背景色,用: • pDC->SetBkColor(RGB(200,200,200)); • 除非背景模式设为不透明,否则背景色被忽略。不透明意味着在绘制文本前,先绘制背景矩形;透明模式意味着文本被绘制在当前背景之上。

  37. 8)打开不透明背景模式,用: • pDC->SetBkMode(OPAQUE); • 9)打开透明背景模式,用: • pDC->SetBkMode(TRANSPARENT);

  38. 2.使用DrawText() 用DrawText()绘制文本,用: pDC->DrawText(Str, rect,//a bounding rectangle DT_CENTER);//analignment centered 其他文本绘制函数包括: ExtTextOut(),该函数裁剪给定矩形外的绘制文本。 TabbedTextOut(),使用用户提供给该函数的跳格键位置表,扩大插入文本中的跳格距离。 DrawState(),用来绘制无效文本,该文本看起来被蚀刻一样。

  39. 例3图标绘制 • 用三种不同的方法装入一个图标。 • 第一种方法,使用一个称为LoadIcon()的应用程序类的成员函数,它从应用程序的资源中装入一个图标; • 第二种方法,用WindowAPI函数LoadImage()直接从一个磁盘文件中装入一个图标; • 第三种方法,用WindowsAPI函数ExtractIcon()从另一个应用程序的可执行文件中抽出一个图标。

  40. 1.从应用程序的资源中装入一个图标 • 装入一个在应用程序资源中定义的图标,用: HICON hIcon; hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);

  41. 2.直接从一个.ico磁盘文件中装入一个图标 从一个.ico文件装入一个图标,使用下面的方法。本例从Wzd.ico装入一个图标。 hicon=(HICON)LoadImage( NULL, “Wzd.ico”, IMAGE_ICON, IMAGE_CURSOR //or IMAGE_ICON 0,0, //width and height LR_LOADFROMFILE); //loadflags

  42. 3.从一个DLL或.exe文件中装入一个图标 • 从另一个应用程序的可执行文件中抽取一个图标,可以用下面的方法。本例中抽取在Wzd.exe中发现的第二个图标。 HINSTANCE hinst=AfxGetInstanceHandle(); hicon=ExtractIcon(hinst, "Debug\\wzd.exe", 1);

  43. 4.绘制一个图标 • 用下面的方法可以把一个图标绘制到任何窗口。这里的(0,0)是图标的左上角坐标。 • pDC->DrawIcon(0,0,hicon); • 5.销毁一个图标 • 必须手工销毁任何一个装入的或者用LoadImage()装入或ExtractIcon()抽取的图标,以避免资源内存泄漏。 • DestroyIcon(hicon);

  44. 例4装入一个位图和绘制一个位图 • 用CBitmap类装入一个在应用程序资源中定义的位图; • 用WindowsAPI函数LoadImage()从一个.bmp文件中装入一个位图添加位图到应用程序的资源中 • 有两种把位图装入到工程中的方法。第一种,用DeveloperStudio的位图编辑器创建一个位图;第二种,用DeveloperStudio的insert/ InsertResource菜单命令下的Import命令装入一个位图。注意分配给位图的ID。

  45. 2.从应用程序的资源中装入位图 • 要把位图装入应用程序中进行绘制,用下面的方法,可以用自己的位图ID替代IDB_WZD。 • CBitmap bitmap; • bitmap.LoadBitmap(IDB_WZD);

  46. 3.从一个.bmp文件中装入位图 在运行时用LoadImage()装入一个位图。 CBitmap bitmap; HBITMAP hbitmap=(HBITMAP)::LoadImage( NULL, "Wzd2.bmp", //name or identifier of image IMAGE_BITMAP, //type of image- 0,0, //desired width and height LR_LOADFROMFILE); //load from file bitmap.Attach(hbitmap);

  47. 4.绘制一个位图 绘制一个位图可以用下面的方法,注意用BitBlt()需要两个设备环境,而不是一个。 CDC dcComp; dcComp.CreateCompatibleDC(pDC); dcComp.SelectObject(&bitmap); //get size of bitmap for BitBlt() BITMAP bmInfo; bitmap.GetObject(sizeof(bmInfo),&bmInfo); //use BitBlt() to draw bitmap pDC->BitBlt(0,0,bmInfo.bmWidth, bmInfo.bmHeight,&dcComp,0,0,SRCCOPY);

More Related