荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Deny (孤苦伶仃一个人,哈哈), 信区: Program
标  题: 『VC++技术内幕』学习笔记(7)
发信站: 荔园晨风BBS站 (Tue Dec 25 20:00:58 2001), 转信

原作者姓名 雷神
文章原始出处 http://www.ai361.com
正文
『VC++技术内幕』学习笔记(7)
雷神
第七篇:图形设备接口(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-1
void 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++对象来表示的。读着怎么这么别扭?举例说
一下。
CBrush是一个GDI的派生类,它在MFC中的层次结构是这样的:CObject派生
CGdiObject派生CBrush,明白了吧。CGdiObject是所有GDI对象的抽象基类。下面
列出的是GDI派生类的列表:
CBitmap:位图是一种位矩阵,每一个显示象素都对应于其中的一个或多个位,可
以用来表示图象,也可以用来创建刷子
CBrush:刷子定义了一种位图形式的象素,可以用来对区域内部填充颜色。
CFont:字体是一种具有某种风格和尺寸的所有字符的完整集合,常常被作为资源
,其中一些依赖某种设备。
CPalette:调色板是一种颜色映射接口,它允许应用程序在不影响其他应用程序的
前提下,可以充分利用输出设备的颜色描绘能力。
CPen:笔是一种用来画线及绘制有形边框的工具,可以指定它的颜色及宽度,并可
以指定画虚线、点线还是实线。
CRgn:区域是由多边形、椭圆二者组合形成的一种范围,可以用来进行填充、裁剪
、鼠标点中测试等等。
以上很容易理解,可以用WINDOWS的画图帮助我们理解。
CGdiObject类很眼生,看过很多代码就没有看到过它,原因是由于CGdiObject类是
所有GDI对象类的虚拟基类,所以我们不必创建CGdiObject类的对象,可以直接构
造它的派生类的对象,例如这样
CPen newPen(PS_DASHDOTDOT,2,(COLORREF) 0);    //黑色的笔宽度为2
但需要注意的是CFont和CRgn的对象建立需要先调用默认的构造函数来构造C++对象
,然后再调用相应的创建函数如:
CreateFont或CreatePolygonRgn等。
CGdiObject类有一个虚拟的析构函数,它派生类的析构函数需要将与C++对象相关
联的GDI对象删除掉,一定要在退出程序之前把构造的CGdiObject派生类对象干掉
。因为一个没有释放的GDI对象会占用很多的内存。
让我们用一个例子跟踪一下GDI对象
//*************************************
//    例子7-2
void CMy10View::OnDraw(CDC* pDC)
{
    pDC->MoveTo (10,10);
    pDC->LineTo (110,10);
    CPen newPen(PS_DASHDOTDOT,10,(COLORREF) 192);    //红色的笔宽度为
10
    CPen * pOldPen=pDC->SelectObject (&newPen);
//在将新对象选进设备环境的同时返回指向前一次被选对象的指针。作用保存原来
的对象,以便完成任务时恢复它。
    pDC->MoveTo (10,20);
    pDC->LineTo (110,20);
    pDC->SelectObject (pOldPen);//把原来的对象恢复
    pDC->MoveTo (10,30);
    pDC->LineTo (110,30);
}
屏幕上应该显示三条线,第一条和第三条一样颜色和粗细因为他们都是用的设备环
境默认的CPen对象,第二条是一条用我们自己设定的CPen对象。我们可以看出在将
新对象选进设备环境的同时返回指向前一次被选对象的指针。作用保存原来的对象
,以便完成任务时恢复它。
Windows还包含有一些可以利用的库存对象,它们不会被删除,因为Windows对企图
删除它们的动作不予理睬。我们可以用SelectStockObject函数将它们选进设备环
境。下面列出的是所有的有关刷子、笔、字体和调色板的库存对象。
//**********************************************************************
*****
//    MSDN中的内容
BLACK_BRUSH       //Black brush.
DKGRAY_BRUSH       //Dark gray brush.
GRAY_BRUSH       //Gray brush.
HOLLOW_BRUSH   //Hollow brush.
LTGRAY_BRUSH       //Light gray brush.
NULL_BRUSH       //Null brush.
WHITE_BRUSH       //White brush.
BLACK_PEN       //Black pen.
NULL_PEN       //Null pen.
WHITE_PEN      //White pen.
ANSI_FIXED_FONT   //ANSI fixed system font.
ANSI_VAR_FONT      // ANSI variable system font.
DEVICE_DEFAULT_FONT       //Device-dependent font.
OEM_FIXED_FONT   //OEM-dependent fixed font.
SYSTEM_FONT       //The system font. By default, Windows uses the system
 font to draw menus, dialog-box controls, and other text. In Windows
versions 3.0 and later, the system font is proportional width; earlier
versions of Windows use a fixed-width system font.
SYSTEM_FIXED_FONT   //The fixed-width system font used in Windows
prior to version 3.0. This object is available for compatibility with
earlier versions of Windows.
DEFAULT_PALETTE   //Default color palette. This palette consists of
the 20 static colors in the system palette.
//**********************************************************************
*********

一个问题:
由于SelectObject函数返回的GDI C++对象指针具有临时性,当程序的空闲处理阶
段或者控制函数返回时应用程序框架会将临时的C++对象删除,我们不能简单的把
这一指针保存在类的数据成员中,而应该借助GetSafeHdc函数将它转化为Windows
的句柄,以便持久的保存GDI的标识。我们将例子7-2做些改动。
//**************************************************
//    例子7-3
void CMy10View::OnDraw(CDC* pDC)
{
    HPEN m_hPen; //一个指向CPen对象的指针
    pDC->MoveTo (10,10);
    pDC->LineTo (110,10);
    CPen newPen(PS_DASHDOTDOT,10,(COLORREF) 192);    //红色的笔宽度为
10
    CPen * pOldPen=pDC->SelectObject (&newPen);    //在将新对象选进设备
环境的同时返回指向前一次被选对象的指针。作用保存原来的对象,以便完成任务
时恢复它。
    m_hPen=(HPEN)pOldPen->GetSafeHandle ();//获得并保存原来对象的句柄
    pDC->MoveTo (10,20);
    pDC->LineTo (110,20);
    pDC->SelectObject (CPen::FromHandle (m_hPen));//把原来的对象恢复,和
例子7-2不同的是通过句柄
    pDC->MoveTo (10,30);
    pDC->LineTo (110,30);
}
补充一下IGDI派生类的Windows handle type列表
CPen         HPEN
CBrush        HBRUSH
CFont        HFONT
CBitmap         HBITMAP
CPalette         HPALETTE
CRgn         HRGN

好了我们已经对GDI有了一些了解,下一篇我们将说说颜色和字体,雷神希望大家
对我的学习笔记提些建议,因为很多东西也许不必说的这么罗嗦,可我知道初学
VC的痛苦,太多的东西看不明白,所以尽量写的详细。文章记录了我学习时的心得
,很多东西是从MSDN查来的,不知道合不合大家(初学者)的口味。

未完待续
下一篇:颜色和字体
正文完


--
 ╭⌒╮ ¤
╭ ╭ ⌒╮
╰ ----╯
///"/"/ 心情预报: 多云到少云,间中会头晕,有时会失魂....
                                                        OICQ:86395
        ftp://192.168.1.201/study/my document

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.1.201]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店