window基础编程 --绘图

来源:互联网 发布:返利网程序源码 编辑:程序博客网 时间:2024/06/14 01:53

前言

  • 绘图涉及到绘图设备(DC)和绘图对象(GDIOBJ)以及图形、坐标系、文字的概念。
  • 简单来所,绘图也就是利用绘图设备(DC),给它适当的工具(绘图对象)然后调用GDI库里的绘图函数进行绘图,所谓GDI,也就是windows Graphics Device Interface的简称,windows有关绘图的函数都在这里面。
  • 绘图设备DC在应用中我们需要拿到它的句柄HDC,这个东西指向具体一块内存,严格来说,BeginPaint函数返回的HDC是指向显存的,也就是它可以操作显卡,在它对应的结构体里,包括了显存可操作的起始地址终止地址等资源,这些我们不需要关系,只需知道各种绘图函数为什么要传入一个HDC即可。
  • 题外:GDI是最简单的绘图库,想要绘制3D图形,有openGL库(需要自己下载)和微软自己创造的DirectX可以选择。

颜色

  • 电脑里用一个字节带表一种颜色,用3基色红、蓝、绿可以构成任何一种颜色,由于每种颜色有2^8=256种大小,所以系统可以混搭出2^24=16M种颜色,系统里的32位颜色其实也就是24位基色+8位透明度的意思。
  • 系统里表示颜色的类型是COLORREF,它其实是DWORD类型,也就是
    unsigned long,无符号32位长整形,可以利用宏RGB(r,g,b)来产生任何一种颜色,这个宏其实就是(DWORD)r<<16|(WORD)g<<8|b
  • 使用函数GetRValue 和 GetPixel可以获得一个颜色数据的基色信息和一个点的COLORREF大小。

简单绘图

使用BeginPaint函数获得绘图设备句柄hdc以后就可以绘制图形了,

使用SetPixel可以画点。
使用MoveTo+LineTo可以画线
使用Rectangle和RoundRect可以画矩形和带曲线边角的矩形
使用Ellispse可以画圆和椭圆
使用Arc可以画曲线

绘图对象

绘图对象也就是给绘图设备添加一个绘图工具,系统有默认的绘图工具,但经常需要我们给它更换一个更合适的,这些工具包括哪些呢,查看更换绘图工具函数SelectObject可以找到这些工具:

Bitmap + Brush +Front + Pen + Region


  • 这些工具统一被默认称为HGDIOBJ对象,其实这只是一个空指针,而具体的工具对应它的句柄,也就是具体的结构体指针,所以你可以放入任何一种工具让它隐式转为HGDIOBJ类型,但无法将HGDIOBJ转为具体的工具,比如对于SelectObject函数,如果你参数2放入一个HBRUSH类型,而又想用HBRUSH类型来接受返回值(旧画刷)将报错,这是很容易犯错的地方。
  • 给绘图设备添加对象的基本流程一般如下:

->创建需要添加的工具
->使用SelectObject将其添加到HDC中,并接收旧的绘图对象
->使用完毕后再调用SelectObject将旧的返回给DC
->使用DeleteObject销毁第一步创建的工具(如果需要)
另外,函数GetStockObject可以不用创建而直接得到系统默认的一些绘图工具,透明画刷就需要从这个函数得到。

图形 和 用位图画图

图形文件,广义上其实可以分两种

光栅图形 - 该文件记录了该图形每一个像素点的颜色
矢量图形 - 文件内记录了图像算法,绘图指令等

矢量图形会小很多,而光栅图形是我们平时经常遇到的,如jpeg,bmp等文件,我们创建的位图其实也就是bmp文件,只是我们画的一般都比较小,比如40*40像素的。

  • 利用位图来画图
    • 资源文件里添加的位图我们只能拿到一个ID号,首先我们得调用LoadBitmap函数拿到它的句柄。
    • 使用CreateCompatibleDC来创建一个内存DC,这个DC是拿来操作内存的,也就是我们申请了一块内存来做图,这里的图我们是看不见的,这块空间的意义其实是一个缓冲区,它的作用后面就知道了,返回值先记作hMedc。
    • 给这个内存DC添加位图工具,SelectOBject(hMedc,hBmp)。
    • 在窗口绘图,使用Bitblt/StretchBlt函数,这两个函数需要传两个DC,前一个是目标DC,也就是真正能显示的DC(BeginPaint的返回值),第二个是目标DC(hMedc),也就是从目标DC找到位图的内存数据然后交给绘图设备进行作图。
    • 将旧的绘图工具返回SelectObject(hMedc,old)
    • 删除位图 DeleteObejct
    • 删除内存DC DeleteDC

用位图来作图的步骤如上,为何不直接从文件里读取然后直接交给绘图设备画上去了,这里是有两点考虑的:
1 , 先把位图数据放进内存,然后再转交给绘图设备(显存)这样的绘图效果会更好。
2,将内存DC的位图数据拷贝到绘图DC时可以实现很多特殊的效果,具体可以参看BitBlt函数的最后一个参数,位图可以展示各种显示效果,但其实都是对位图数据的操作。
最后,StrechBlt函数是来拿来放大/缩小位图,而这两个函数都能只显示位图的一部分。

坐标系

电脑里的坐标系分为设备坐标系和逻辑坐标系,可不要以为窗口的坐标系就是以1个像素(Pixel)为单位的,像素其实是显示器这个设备的坐标系单位(device unit),而窗口的坐标系刚好又是1个逻辑坐标系(logic unit)默认对应1个像素,所以刚好是1个像素。- 设备坐标系对应不同的设备是不一样的,显示器是1个像素,而打印机却是1/1440英寸。- 逻辑坐标系是可以自己定义的,需要说明的是像素并不是实际存在的长度单位。

改变程序里的坐标系单位可以使用

SetMapMode(HDC hdc,int fnMapMode)

这里的第二个参数决定了各种坐标系的选取方法,值得一提的是,这个函数的真实意义是各种坐标系之间的映射关系。
参数fnMapMode选取:

风格 对应关系 MM_TEXT 1逻辑坐标 = 1 像素 MM_HIENGLISH 1逻辑坐标 = 0.001英寸 MM_LOENGLISH 1逻辑坐标 = 0.01英寸 MM_HIMETRIC 1逻辑坐标 = 0.01mm MM_LOMETRIC 1逻辑坐标 = 0.1mm MM_TWIPS 1逻辑坐标 = 1/1440英寸 MM_ISOTROPIC 自定义对应关系 MM_ANISOTROPIC 自定义对应关系

最后两个自定义对应的关系的不仅可以自定义对应比例,还能定义XY轴方向,如果是具体数字的风格XY方向都是X右Y下为正。
使用SetWindowExtEx和SetViewportExtEx可以自定义比例关系。
第一个函数的x,y说明一个坐标代表几个逻辑坐标单位。
第二个函数的x,y说明一个逻辑单位占几个设备坐标单位。
这种自定义风格的更大意义在于对任何一种未知设备的坐标映射转换。

文字和字体

  • 我们可以使用TextOut/DrawText函数在窗口中绘制文字,但DrawText函数更加强大,它的最后一个参数可以和画bitmap一样有多种风格,比如文字在矩形区域内的对齐方式,对转义字符进行处理,控制字符换行输出等。同时,还有一个ExtTextOut函数可以指定字符之间的间距。
    最后,SetTextColor指定文字颜色(其实添加PEN也可以)
    SetBkColor指定文字背景色
    SetBkMode指定文字背景是否透明

  • 通过添加绘图对象FONT可以改变画出来的文字字体

    • 创建一个FONT句柄,指明具体的字体文件,函数CreateFont
    • 添加字体到绘图设备中,SelectObject
    • 画完以后改回默认字体SelectObject
    • 删除创建的字体句柄,DeleteObject,这一点很重要,因为中文字体加载以后所占用的内存都比较大,这是很有必要去释放的
0 0