• 在窗口中绘图(转)


    图形设备接口(GDI)与设备描述表(DC)

    图形设备接口(GDI)
    许多MS-DOS程序都直接往视频存储区或打印机端口输送数据, 
    这种 做法的不利之处在于需要对每种显示卡或打印机类型提供相应的驱动程序。
    Windows则提供了一抽象的接口,称之为图形设备接口(GDI)。
    Windows 己经提供了各种显示卡及打印机的驱动程序,
    这样我们的程序就可以不必关心与系统相连的显示卡及打印机的类型。
    我们的程序可以通过调用 GDI函数和硬件打交道,
    而各种GDI函数会自动参考被称为设备环境(CDC)的数据结构。
    Windows会自动将设备环境结构映射到相 应的物理设备,并且会提供正确的输入输出指令。

    设备描述表(DC)

    在Windows环境中,各程序的输出必须限制在自己的窗口中。
    GDI使用一种简单的机制保证在窗口中画图的各程序遵循这个规则。
    这 种机制即为设备描述表(DC);

    当Windows程序在屏幕、打印机或其它设备上画图时,
    它并不是将像素直接输出到设备上,而是将图绘制到由设备描述表表示的逻辑意义上 的"显示平面"上去。

    设备描述表是深寓于Windows中的一种数据结构,
    它包含GDI需要的所有关于显示平面情况的描述字段,包括相连的物理设备和各种各样的 状态信息。

    设备描述表对象
    在使用MFC编制Windows程序时,设备描述表具有更加突出的作用。
    除了可 作为通往各种设备的桥梁之外,设备描述表对象还封装了程序用来产生输出的GDI函数。
    在MFC中,你不用捕获设备描述表句柄和调用GDI输出函 数,至少不必直接捕获和调用,
    而是通过创建一设备描述表对象并调用它的成员函数来画图。

    设备描述表句柄
    在平面上画图之前,Windows程序从GDI获取设备描述表句柄,
    并在每次调 用完GDI输出函数时将句柄返回给GDI。
    在MFC应用程序中获取设备描述表的一种方法是调用CWnd::GetDC,
    它返回指向表示 Windows设备描述表的CDC对象的指针。
    在画图完毕,要用CWnd::ReleaseDC释放指针(注:在OnPaint处理程序中,不用 显示调用这两个函数)

    CDC派生类
    为了避免获取和释放设备描述表所带来的麻烦,
    MFC提供了一些CDC派生类,如 CPaintDC,CClientDC,CWindowDC这些类被设计为可直接进行实例化。
    各个类的构造函数和析构函数调用相应的函数捕获和释 放设备描述表,
    从而便得设备描述表的使用非常方便简捷。

    例如:
    CPaintDC dc(this);
    //Do some drawing
    传送给类构造函数的指针确定了设备描述表 所属的窗口。

    设备描述表属性
    当使用CDC输出函数在屏幕上画图时,
    输出的某些特性并没有在函数调用过程中规 定(采用系统默认的属性画图),
    但我们可以通过设备描述表自身获得或得新设置属性。
    MFC提供了获得和设置这些属性的函数,我们可以用这 些函数方便地改变画图时的默认属性。
    例如:
    CDC::SetTextColor//设置文本颜色
    CDC::GetTextColor// 获得文本颜色
    CDC::SetBkColor//设置背景颜色
    CDC::SetBkMode//设置背景模式
    CDC::SetMapMode// 设置映射模式
    CDC::CDC::SetROP2//设置绘图模式
    CDC::MoveTo//当前位置
    CDCL::SelectObject// 当前画笔,当前画刷,当前字体

    (如果想忽略背景色,可将背景设置为"Transparent",dc.SetBkMode(TRANSPARENT);)

    SelectObject函数
    最常用来定义设备描述表属性的CDC函数是SelectObject。
    例如:
    CPen pen(PS_SOLID,2,RGB(0,192,0));
    CPen* pOldPen = dc->SelectObject(&pen);//把新的CDC对象选入设备描述表,同时保存旧的CDC对象
    dc->Ellipse(0,0,100,100);
    dc.SelectObject(pOldPen);//

    绘图模式与SetROP2
    GDI将像素点输出到逻辑平面上时,它不只是简单地输出像素点颜色。
    相 反,它能过一系列的布尔运算将输出像素点的颜色和目标位置上像素点的颜色合成一起。
    它所使用的逻辑关系由设备描述表当前的绘图模式确定。
    使 用CDC::SetROP2(Set Raster Operation To)可更改绘图模式。
    默认绘图模式为R2_COPYPEN,它将将像 素点复制到显示平面上。

    映射模式

    默认映射模式
    固定比例映射模式
    可编程映射模式

    简单地说,映射模式是设备描述表的属性,用于确定从逻辑坐标值到设备坐标值的转换方式。

    默认的映射模式

    默认的映射模式使MM_TEXT,它使以象素为单位的。X轴向左为正,Y轴向下为正。默认的坐标原点在左上角。

    固定比例映射模式

    固定比例的映射模式有MM_LOMETRIC、MM_HIMETRIC、MM_LOENGLISH、MM_HIENGLISH、MM_TWIPS 种。
    它们默认的坐标原点都使在左上角。其区别在于每一个逻辑单位对应的物理大小不一样。
    所对用的逻辑单位分别为0.1毫米,0.01毫 米,0.01英寸,0.001英寸,1/1440英寸(0.0007英寸)。

    可变比例映射模式(可编程映射模式)

    对于可变比例的映射模式用户可以自己定义一个逻辑单位代表的大小,其大小可以任意。
    也可以让这个大小随环境改变而改变。有 MM_ISOTROPIC,MM_ANISOTROPIC这两种映射模式。
    其逻辑单位的大小等于视口范围和窗口范围的比值。
    两者的不同在 于前者要求X轴和Y轴的度量单位必须相同,而后者没有这样的限制。

    可编程映射模式
    MM_ISOTROPIC和MM_ANISOTROPIC是由用户决定从逻辑坐标值转换 成设备坐标值的方式,
    即是由用户决定一个逻辑单位等于多少个设备单位(cm,mm,m等),而不是由Windows决定。
    所以被称之为可 编程映射模式;
    MM_ISOTROPIC和MM_ANISOTROPIC映射模式最常用于根据窗口尺寸按比例自动调节画图的输出大小的场合。

    MM_ISOTROPIC和MM_ANISOTROPIC映射模式的区别
    前者中X方向和Y方向具有同一个缩放比例因子,而后者两个方向可以 单独缩放;

    例子:
    CRect rect;
    GetClientRect(&rect);
    dc.SetMapMode(MM_ISOTROPIC);
    dc.SetWindowExt(500,500);// 设置窗口范围,将窗口的逻辑尺寸高为500单位×500单位
    dc.SetViewportExt(rect.Width(),rect.Height());// 设置视口范围
    dc.Ellipse(0,0,500,500);

    注:窗口的尺寸以逻辑单位计算,视口的尺寸以设备单位或像素计算。
    特别说明
    MM_TEXT为默认映射模式,其原点在窗口的左上 角,X轴的正向向右,Y轴的正向向下,
    并且一个逻辑单位对应于设备坐标下的一个象素

    其它映射模式则原点不变,只是Y轴会翻转使正向朝上,并且逻辑单位被按比例转换为实际距离大小,而不是像素数。
    需要注意的是,使用公制映射 模式(非默认映射模式)时,为使输出可见,Y坐标必须为负值。
    例如:
    dc.Rectangle(0,0,200,100);//默认模式 下画图
    dc.SetMapMode(MM_LOENGLISH);//改变映射模式
    dc.Rectangle(0,0,200,-100);// 画图

    传送给CDC输出函数的是逻辑坐标值。
    设备坐标值是指窗口中相应的像素点位置。


    Windows中的几种坐标体系

    1、屏幕坐标

    屏幕坐标描述物理设备(显示器、打印机等)的一种坐标体系,
    坐标原点在屏幕的左上角,X轴向右为正,Y轴向下为正。度量单位是象素。
    原 点、坐标轴方向、度量单位都是不能够改变的。

    2、设备坐标(又称物理坐标)

    设备坐标是描述在屏幕和打印机显示或打印的窗体的一种坐标体系。
    默认的坐标原点是在其客户区的左上角。X轴向右为正,Y轴向下为正。
    度 量单位为象素。原点和坐标轴方向可以改变,但是度量单位不可以改变。

    3、逻辑坐标

    逻辑坐标是在程序中控制显示,打印使用的坐标体系。
    该坐标系与定义的映射模式密切相关。默认的映射模式是MM_TEXT。
    我们可以 通过设置不同的映射模式来改变该坐标体系的默认行为。

    注意:
    首先,要记住两点:
    1。设备坐标的(0, 0)点始终是客户区的左上角。
    2。我们在绘图时指定的点全部都是逻辑坐 标点。

    坐标转换
    调用CDC::LPtoDP可以将逻辑坐标转换为设备坐标;
    高用 CDC::DPtoLP可以将设备坐标转换为逻辑坐标;

    什么时候用什么坐标系

    • 可以认为CDC的所有成员函数都以逻辑坐标作为参数
    • 可以认为CWnd的所有成员函数都以设备坐标作为其参数
    • 所有选中测试操作中都应该考虑设备坐标。区域的定义应采用设备坐标。
      某些像CRect::PtInRect之类的函数只有在采用 设备坐标参数时才会保证有正确的结果
    • 将一些需要长期使用的值用逻辑坐标或物理坐标来保存。
      如果用逻辑坐标来保存某点的坐标的话,那么只要用户对窗口进行一下滚动,该 点的坐标就不再有效了。
    • 鼠标单击事件下得到的坐标都是设备坐标!

    移动原点
    CDC::SetViewportOrg()移动视口的原点 
    CDC::SetWindwosOrg() 移动窗口的原点
    正常情况下,只能使用其中之一,同时使用两个会搞提一团糟。

    获取设备信息
    获得系统分辨率
    CClientDC dc(this);
    int cx = dc.GetDeviceCaps(HORZRES);
    int cy = dc.GetDeviceCaps(VERTRES);

    用GDI绘图

    MFC的CDC类将相关的GDI函数封装在类成员函数中。
    在设备描述表对象中或通过指向设备描述表对象的指针可以方便地调用这些函数

    画线
    dc.MoveTo(0,0);//设置当前位置
    dc.LineTo(100,100);// 指定一个线的终点位置

    画圆
    dc.Ellipse(0,0,100,100);
    CRect rect(0,0,100,100);
    dc.Ellipse(rect);

    画矩形
    dc.Rectangle(0,0,100,100);//画一个带直角的矩形

    GDI画笔和CPen类
    Windows用当前选入设备描述表的画笔绘制直线和曲线,
    并给用 Rectangle,Ellipse以及其他图形生成函数画出的图形镶画边框。
    默认画笔画出的是一个像素点宽的黑色实线。
    如果要改变画线 方式,则需创建一个GDI画笔,并由CDC::SelectOjbect将它选设备描述表

    MFC用类CPen表示GDI画笔。

    创建画笔的方法
    创建画笔的最简单的方法是构造一个CPen对象并把定义画笔所用的参数都传送给该对象
    CPen pen(PS_SOLID,1,RGB(255,0,0));

    创建画笔的第二种方法是构造 一个汉有初始化的CPen对象并调用CPen::CreatePen:
    CPen pen;
    pen.CreatePen(PS_SOLID,1,RGB(255,0,0));

    创建画笔的第三种方法是构造一个没有初始化的CPen对象,向LOGPEN结构中填充描述画笔特性的参数
    ,然后调用 CPen::CreatePenIndirect生成画笔
    CPen pen;
    LOGPEN lp;
    lp.lognStyle = PS_SOLID;//样式
    lp.lopnWidth.x = 1;//宽度
    lp.lopnColor = RGB(255,0,0);//颜色
    pen.CreatePenIndirect(&lp);

    从以上的画笔定义可以看出,定义画笔需要三个特性:样式,宽度和颜色。
    画笔的样式说明请参见MSDN

    GDI画刷和CBrush类
    在默认情况下,则Rectangle,Ellipse以及其它CDC函数画 出的封闭图形填充着白色像素点。
    通过创建GDI画刷并在画图之前将它选入设备描述表,可以改变图形的填充颜色。
    MFC的CBrush类封 装了GDI画刷。
    画刷有三种基本类型:单色、带阴影和带图案。
    单色画刷填充的单色。
    阴影线画刷采用预先定义好的交叉线图案填充图 形。
    图案画刷用位图来填充图形。

    创建单色画刷的方法类似于创建画笔,如下所示:
    CBrush brush(RGB(255,0,0));

    CBrush brush;
    brush.CreateSolidBrush(RGB(255,0,0));

    创建带阴影线画刷
    CBrush brush(HS_DIAGCROSS,RGB(255,0,0));//阴影索引,COLORREF值

    CBrush brush;
    brush.CreateHatchBrush(HS_DIAGCROSS,RGB(255,0,0));
    HS_DIAGCROSS 是可供选择的六种阴影线样式之一,其它样式请参见MSDN

    注意:
    在用阴影线画刷填充时,除非用CDC::SetBkColor改变设备描述表的当前背景色,
    或用 CDC::SetBkMode把背景模式OPAQUE改成TRANSPARENT,禁止背景填充,
    否则WIndows就以默认的背景钯(白色)填 充阴影色线间的空白处。

  • 相关阅读:
    mysql数据库表名区分大小写
    Maven配置和使用
    Centos7修改网卡名称
    mongo启动报错问题处理
    zabbix分布式部署和主机自动发现
    zabbix-server、proxy、agent的分布式部署步骤
    zabbix常见错误处理方式
    git用ssh方式下载和提交代码
    CentOS7使用阿里云的yum源
    VMware三种网络模式详解
  • 原文地址:https://www.cnblogs.com/chinasasu/p/1707717.html
Copyright © 2020-2023  润新知