《09GDI编程2—文字、位图与图标(windows编程技术).pdf》由会员分享,可在线阅读,更多相关《09GDI编程2—文字、位图与图标(windows编程技术).pdf(50页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、1 第 9 章 GDI 编程 2文字、位图与图标与 DOS 等传统字符界面用点阵模板显示文字不同,GUI 中的文字一般是利用轮廓字体中的控制点数据经计算后再绘制出来的。Windows 中的文字,采用的是基于二次贝塞尔曲线的 TrueType 轮廓字体(字体文件为*.TTF)。MFC 中的字体类为CFont,字体对象选入DC后,再用于TextOut 等函数的文字绘制输出。位图是指由像素阵列组成的数字化点阵图像,是GUI 的基本元素。位图可分成与设备相关和无关的两类,分别用于图像的显示和存储,对应的 MFC 类分别为CBitmap 和 CImage。图标是一类大小固定的方型小位图,用于代表应用程序
2、或文档子窗口。为了满足不同显示设备和不同使用目的的需要,在一个程序的图标资源中,一般包含多个不同大小和位数的图像。MFC 为应用程序提供了默认的图标,可用资源编辑器对其进行修改。9.1 输出文本一般使用 CDC 类的 TextOut 等函数,采用 DC 中的当前字体和文本颜色等来输出文本。还可以用SetTextAlign 函数来设置文本的对齐方式,用 SetTextColor 和 SetBkColor 函数来分别设置文本的前景和背景颜色。9.1.1 文本输出函数在 CDC 类中,封装了多种文本输出函数,它们都是使用当前的字体、文本颜色和背景颜色,在屏幕或打印机上输出文本(绘制文字)。常用的文本
3、输出函数有基本的TextOut、矩形区域的DrawText 和可裁减和调字间距的扩展的 ExtTextOut。1TextOut TextOut 的函数原型为:virtual BOOL TextOut(int x,int y,LPCTSTR lpszString,int nCount);BOOL TextOut(int x,int y,const CString&str);其中,x 与 y为显示串的左上角坐标,lpszString 或 str为要显示的文本串,nCount 为串 lpszString2 中的字符数。例如:pDC-TextOut(10,30,LTest text);2DrawTex
4、t DrawText 的函数原型为:virtual int DrawText(LPCTSTR lpszString,int nCount,LPRECT lpRect,UINT nFormat);int DrawText(const CString&str,LPRECT lpRect,UINT nFormat);其中,lpszString 或 str 为要显示的文本串,nCount 为串 lpszString 中的字符数,lpRect 为指定的显示区域,nFormat 为显示格式,可取表9-1 中值的位或“|”组合。表 9-1 文本显示格式nFormat 的常用取值符号常量含义DT_BOTTOM
5、 文本底对齐,必需与DT_SINGLELINE.同时使用DT_CALCRECT 计算并调整矩形的宽与高DT_CENTER 水平居中显示文本DT_EXPANDTABS 扩展 Tab 字符(默认为8 个字符宽)DT_LEFT 居左显示文本DT_NOCLIP 不剪裁(可提高显示速度)DT_NOPREFIX 终止对表示加下划线的前缀字符&的处理DT_RIGHT 居右显示文本DT_SINGLELINE 单行显示文本,忽略回车和换行符DT_TABSTOP 设置 Tab 的字符位数,该数放在nFormat 的高位字节中DT_TOP 文本顶对齐,必需与DT_SINGLELINE.同时使用DT_VCENTER
6、垂直居中显示文本DT_WORDBREAK 文本行超过矩形区域的宽时换行3ExtTextOut ExtTextOut 的函数原型为:virtual BOOL ExtTextOut(int x,int y,UINT nOptions,LPCRECT lpRect,LPCTSTR lpszString,UINT nCount,LPINT lpDxWidths);3 BOOL ExtTextOut(int x,int y,UINT nOptions,LPCRECT lpRect,const CString&str,LPINT lpDxWidths);其中,nOptions 可为 ETO_CLIPPED
7、(裁剪)/ETO_OPAQUE(不透明),lpRect 为裁剪矩形(可为 NULL),lpDxWidths 指定字符的间距(为NULL 时使用默认间距)。9.1.2 设置文本对齐可用 CDC 类的 SetTextAlign 函数来设置TextOut 和 ExtTextOut 输出文本时的对齐方式:UINT SetTextAlign(UINT nFlags);其中,nFlags 可为表 9-2 中值的位或“|”组合,默认的文本对齐方式为“左顶”即“TA_LEFT|TA_TOP”。表 9-2 文本对齐标志nFlags 的取值符号常量含义符号常量含义TA_BASELINE 基线对齐TA_NOUPDA
8、TE 不更新当前位置TA_BOTTOM 底对齐TA_RIGHT 居右显示文本TA_CENTER 居中显示文本TA_TOP 顶对齐(默认值)TA_LEFT 居左显示文本(默认值)TA_UPDATE 更新当前位置例如(输出见图9-1):RECT rect;GetClientRect(&rect);int w=rect.right,h=rect.bottom;pDC-TextOut(10,10,L 这是左上角);/默认为“TA_LEFT|TA_TOP”pDC-SetTextAlign(TA_CENTER);pDC-TextOut(w/2,10,L这是顶部中央);pDC-SetTextAlign(TA
9、_RIGHT);pDC-TextOut(w-10,10,L这是右上角);pDC-SetTextAlign(TA_BOTTOM);pDC-TextOut(10,h-10,L这是左下角);pDC-SetTextAlign(TA_BOTTOM|TA_RIGHT);pDC-TextOut(w-10,h-10,L这是右下角);4 图 9-1 文本对齐例的输出9.1.3 设置文本颜色在 8.3.5 中已经讲过,可使用CDC 类的成员函数SetTextColor 和 SetBkColor 来分别设置输出文本的前景色和背景色(默认的文本前景色为黑色、背景色为空):virtual COLORREF SetTex
10、tColor(COLORREF crColor);virtual COLORREF SetBkColor(COLORREF crColor);例如:pDC-SetTextColor(RGB(255,0,0);pDC-SetBkColor(RGB(0,0,128);9.2 字体为了能使用不同的字体和大小来输出文本串,必须使用作为GDI对象的CFont 类。Windows 和常用的字处理软件(如Word)和绘图软件(如CorelDraw)等应用软件会提供多种与设备无关的字体,主要是TrueType 类型的轮廓字体。9.2.1 CFont类CFont 类是 CGDIObject的派生类:CObjec
11、tCGDIObject CFont。只有一个默认构造函数 CFont();必须用字体创建成员函数CreateFontIndirect 或 CreatePointFont Indirect 来进行初始化。1字体创建函数CFont 类的字体创建成员函数的原型有:5 BOOL CreateFont(int nHeight,int nWidth,int nEscapement,int nOrientation,int nWeight,BYTE bItalic,BYTE bUnderline,BYTE cStrikeOut,BYTE nCharSet,BYTE nOutPrecision,BYTE nC
12、lipPrecision,BYTE nQuality,BYTE nPitchAndFamily,LPCTSTR lpszFaceName);BOOL CreateFontIndirect(const LOGFONT*lpLogFont);BOOL CreatePointFont(int nPointSize,LPCTSTR lpszFaceName,CDC*pDC=NULL);BOOL CreatePointFontIndirect(const LOGFONT*lpLogFont,CDC*pDC=NULL);注意:CFont 类的这些逻辑字体创建函数,并不是从无到有创建一个全新的GDI 字体,
13、而只是从Windows 的物理字体库中选择一个与所设置参数最匹配的字体。在这些字体创建函数中,CreateFont 的参数有很多,与下面要讨论的逻辑字体结构LOGFONT 中字段相对应。而 CreatePointFont 函数则提供了创建字体的一种简单方法,一般只需提供字体的大小和名称两个参数:nPointSize 为字体大小,以 0.1 点(像素/墨点/磅数)为单位。汉字的字号与nPointSize值及磅数的对应关系见表9-3 和图 9-2,图书和文献的正文一般为5 号宋体字。另外,若 pDC 非空,则系统会将设备单位点自动转换为pDC 中的映射模式所指定的逻辑单位。lpszFaceName
14、 为字体名称字符串的指针,常用的中文字体名有:宋体、仿宋_GB2312、楷体 _GB2312、黑体、隶书、幼圆等,常用的英文字体名有:Times New Roman、Arial Narrow和 Courier New 等,参见图9-3。表 9-3 汉字字号与nPointSize 值及磅数的对应关系汉字字号nPointSize 值磅数汉字字号nPointSize 值磅数初号420 42 四号140 14 小初360 36 小四120 12 一号260 26 五号105 10.5 小一240 24 小五90 9 二号220 22 六号75 7.5 小二180 18 小六65 6.5 三号160 1
15、6 七号55 5.5 小三150 15 八号50 5 6 图 9-2 汉字的字号与磅数图 9-3 常用的中英文字体例如:CFont font;/定义字体对象font.CreatePointFont(105,L宋体);/创建 5 号宋体字下面是输出如图9-2 的不同大小字符串的OnDraw 函数(可以创建一个采用传统界面的单文档 MFC 应用程序项目Font):void CFontView:OnDraw(CDC*pDC)CFont font,*pOldFont;/定义字体对象和指针int iSize,y=0;/定义字体大小变量和垂直坐标变量/定义对应于汉字字号的nPointSize值数组7 in
16、t fs16=420,360,260,240,220,180,160,150,140,120,105,90,75,65,55,50;wchar_t buf40;/定义字符串缓冲区 /定义字号与字体名称的字符串对象CString sFontNum,sFontName=L宋体;for(int i=0;i SelectObject(&font);/选入字体对象sFontNum=GetFontNumber(iSize);/获取当前字号swprintf_s(buf,40,L这是%s%s字(%g 磅),sFontName,sFontNum,iSize/10.0);/生成输出的字符串pDC-TextOut(
17、0,y,buf);/输出字符串pDC-SelectObject(pOldFont);/选出字体font.DeleteObject();/删除字体对象y+=fsi/6;/更新 y 值 其中用到了将字体大小iSize 转换为中文字号串sFontNum 的自定义 函数 GetFontNumber:CString CFontView:GetFontNumber(int size)switch(size)case 420:return L初号;case 360:return L小初;case 260:return L一号;case 240:return L小一;case 220:return L二号;c
18、ase 180:return L小二;case 160:return L三号;case 150:return L小三;case 140:return L四号;8 case 120:return L小四;case 105:return L五号;case 90:return L小五;case 75:return L六号;case 65:return L小六;case 55:return L七号;case 50:return L八号;return L未知;还需要在视图类的头文件中,添加此函数的原型:CString GetFontNumber(int size);下面的代码段的输出对应于图9-3:CF
19、ont font,*pOldFont;CString fontNames=L宋体,L 仿宋 _GB2312,L 楷体 _GB2312,L 黑体,L隶书,L幼圆,LTimes New Roman,LArial Narrow,LCourier New;int size=180,x=0,y=0;for(int i=0;i SelectObject(&font);pDC-TextOut(x,y,fontNamesi);pDC-SelectObject(pOldFont);font.DeleteObject();x+=200;if(i+1)%3=0)x=0;y+=size/6;9 2逻辑字体结构字体间接
20、创建函数CreateFontIndirect 和 CreatePointFontIndirect 中所使用的逻辑字体结构 LOGFONT 的定义为(wingdi.h):typedef struct tagLOGFONT /lf LONG lfHeight;/字体的逻辑高度LONG lfWidth;/字体平均宽度的逻辑值LONG lfEscapement;/字符串底线与水平线的夹角(单位为0.1 度)LONG lfOrientation;/每个字符的底线与水平线的夹角(单位为0.1 度)LONG lfWeight;/字体的粗细(磅数=每 1000 点中所含的像素/墨点数),BYTE lfItal
21、ic;/TRUE则字体为斜体字BYTE lfUnderline;/TRUE则字体带下划线BYTE lfStrikeOut;/TRUE则字体带删除线BYTE lfCharSet;/字符集BYTE lfOutPrecision;/输出字体的精度BYTE lfClipPrecision;/输出时字体被裁剪的精度BYTE lfQuality;/输出质量BYTE lfPitchAndFamily;/字符间距与字体家族WCHAR lfFaceNameLF_FACESIZE;/字体名称 LOGFONTW;typedef LOGFONTW LOGFONT;下面是该结构中的各个参数的含义及取值:lfHeight
22、 0 时,高度被转化为设备单位,大小相对于字体的网格高度。=0 时,使用合理的默认高度。GetDeviceCaps(LOGPIXELSY),720);其中,MulDiv 将前两个32 位整数相乘得一个64 位整数,然后再除以第3 个 32 位整数,而函数 GetDeviceCaps 可用来获得各种显示设备的信息,LOGPIXELSY指垂直方向上10 每逻辑英寸所含的像素数。lfWidth 字体平均宽度的逻辑值,为0 时,会自动选择一个与高度最匹配的值。lfWeight的单位为千分比,取值范围为0(全白)1000(全黑),0 为默认粗细、400为正常、700 为粗体,可取表9-4 中列出的符号常
23、量。表 9-4 字体粗细lfWeight 的取值符号常量磅数符号常量磅数FW_DONTCARE 0 FW_MEDIUM 500 FW_THIN 100 FW_SEMIBOLD 600 FW_EXTRALIGHT 200 FW_BOLD 700 FW_LIGHT 300 FW_EXTRABOLD 800 FW_NORMAL 400 FW_HEA VY 900 lfCharSet 可取预定义的字符集符号常量,常用的有:ANSI_CHARSET/=0 CHINESEBIG5_CHARSET/=136 DEFAULT_CHARSET/=1 GB2312_CHARSET/=134 CHINESE_GB2
24、312/=134?OEM_CHARSET/=255 SYMBOL_CHARSET/=2 lfOutPrecision 决定输出的字体与所设定的各种参数的匹配方式,可取下列符号常量值:OUT_DEFAULT_PRECIS/=0 默认精度OUT_DEVICE_PRECIS/=5 选择同名字体中的设备字体匹配OUT_OUTLINE_PRECIS/=8 选择轮廓字体匹配OUT_RASTER_PRECIS/=6 选择同名字体中的光栅字体匹配OUT_STRING_PRECIS/=1 只在获取时返回:光栅字体OUT_STROKE_PRECIS/=3 Win95:选矢量字体;Win95/NT:只在获取时返回:
25、TrueType、轮廓或矢量字体OUT_TT_ONL Y_PRECIS/=7 只选择 TrueTyope 字体匹配,若没有则采用默认OUT_TT_PRECIS /=4 选择同名字体中的TrueTyope 字体匹配11 lfClipPrecision 决定如何裁剪超出剪裁区的字体,可取下列符号常量值:CLIP_DEFAULT_PRECIS/=0 默认精度CLIP_STROKE_PRECIS/=2 只在获取时返回:光栅、矢量或TrueType 字体lfQuality 可取下列符号常量值:CLIP_DEFAULT_PRECIS/=0 默认质量DRAFT_QUALITY/=1 草稿质量PROOF_QU
26、ALITY/=2 校样质量lfPitchAndFamily中的字符间距(pitch)占字节的低2 位,可取下列符号常量值:DEFAULT_PITCH/=0 默认间距FIXED_PITCH/=1 固定间距VARIABLE_PITCH/=2 可变间距字体家族(family)占字节的47 位,可取下列符号常量值:FF_DECORATIVE/=54 装饰性新奇字体,如Old English FF_DONTCARE/=04 不关心或不知道FF_MODERN/=34 等宽字体,有或无衬线,如 Pica、Elite 和 CourierNew?FF_ROMAN/=14 罗马字体,变宽、有衬线,如MS?Seri
27、f FF_SCRIPT/=44 手迹字体,看上去向是手写体,如Script 和 Cursive FF_SWISS/=2GetCurrentFont();LOGFONT logFont;pFont-GetLogFont(&logFont);也可以先创建一个字体对象,再获取对应的逻辑字体结构。例如:CFont font;font.CreatePointFont(120,L黑体);/创建小四号黑体字LOGFONT logFont;font.GetLogFont(&logFont);9.2.2 字体公用对话框为了方便用户选择各种字体参数,可使用如图9-4 所示的字体公用对话框。13 图 9-4 字体公
28、用对话框可用该对话框获取字体的名称、大小、字型、效果、字符集等创建字体对象所需的参数值,还能获取设置字体前景色所需的颜色值,但是却不能得到输出字体的角度值。使用字体公用对话框需要用到CFontDialog 类。CFontDialog 类的构造函数为CFontDialog(LPLOGFONT lplfInitial=NULL,DWORD dwFlags=CF_EFFECTS|CF_SCREENFONTS,CDC*pdcPrinter=NULL,CWnd*pParentWnd=NULL);其中,lplfInitial为上面所讲的逻辑字体结构的指针,dwFlags 为对话框的可选参数,CF_EFFE
29、CTS表示对话框中有删除线和下划线复选框与选择颜色的下拉式组合框,CF_SCREENFONTS 则使得对话框中只列出系统支持的显示字体。如果设置了CF_EFFECTS 标志,还可以用字体公用对话框的公共数据成员m_cf 结构的rgbColors 域,来初始化(和获取)字体的颜色(不过只能为16 种系统颜色之一,否则会显示为黑色)。例如:fontDlg.m_cf.rgbColors=m_textColor;CFontDialog 类的常用成员函数有:virtual int DoModal();/显示对话框,返回IDOK 或 IDCANCEL void GetCurrentFont(LPLOGFO
30、NT lplf);/返回当前逻辑字体结构到lplf CString GetFaceName()const;/返回字体名称串CString GetStyleName()const;/返回字体风格名称串int GetSize()const;/返回所选择的字体大小,以0.1 点为单位int GetWeight()const;/返回字体的磅数COLORREF GetColor()const;/返回所选择的字体颜色BOOL IsStrikeOut()const;/若选中了删除线,则返回TRUE BOOL IsUnderline()const;/若选中了下划线,则返回TRUE BOOL IsBold()c
31、onst;/若选中了粗体或粗斜体,则返回TRUE BOOL IsItalic()const;/若选中了斜体或粗斜体,则返回TRUE 9.2.3 字体的选择与使用若只是按名称和大小来创建字体,可直接使用CFont 类的成员函数CreatePointFont。若还要设置字体粗细、下划线、斜体和方向等,则需要 自己编写 一个函数SetMyFont 来使用字14 体创建函数CreateFont,很多参数都可以用默认值,例如:在视图类的头文件中定义若干类变量:CFont m_font;LOGFONT m_logFont;wchar_t m_fontNameLF_FACESIZE;int m_iFontS
32、ize;COLORREF m_textColor;BOOL m_bItalic,m_bBold,m_bUnderline,m_bStrikeOut;.注意,m_fontName不能被定义成空指针(LPCTSTR m_fontName;),并直接使用它。在构造函数中初始化:CFontView:CFontView().wcscpy_s(m_fontName,LF_FACESIZE,L宋体);m_iFontSize=120;m_font.CreatePointFont(m_iFontSize,m_fontName);m_font.GetLogFont(&m_logFont);m_textColor=
33、RGB(0,0,0);m_bItalic=false;m_bBold=false;m_bUnderline=false;m_bStrikeOut=false;.下面是 自定义 函数 SetMyFont 的原型:BOOL SetMyFont(CDC*pDC,LPCTSTR faceName,int size,COLORREF col=RGB(0,0,0),int angle=0,BOOL italic=FALSE,BOOL bold=FALSE,BOOL underline=FALSE,BOOL strikeOut=FALSE);下面是 SetMyFont 函数的函数体:15 BOOL CFon
34、tView:SetMyFont(CDC*pDC,LPCTSTR name,int size,COLORREF col,int angle,BOOL italic,BOOL bold,BOOL underline,BOOL strikeOut)int height=-MulDiv(size,pDC-GetDeviceCaps(LOGPIXELSY),720);CFont font;/m_font.DeleteObject();并用 m_font代替 font:BOOL bOk=font.CreateFont(height,0,angle,angle,bold?700:400,italic,und
35、erline,strikeOut,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_PITCH|FF_DONTCARE,name);if(bOk)font.GetLogFont(&m_logFont);pDC-SelectObject(font);pDC-SetTextColor(col);return bOk;可以在自己定义的菜单项ID_GET_FONT的事件处理函数OnGetFont 中打开字体公用对话框,获得字体参数:void CFontView:OnGetFont()CF
36、ontDialog fontDlg(&m_logFont);fontDlg.m_cf.rgbColors=m_textColor;if(fontDlg.DoModal()=IDOK)wcscpy_s(m_fontName,LF_FACESIZE,fontDlg.GetFaceName();m_iFontSize=fontDlg.GetSize();m_textColor=fontDlg.GetColor();m_bItalic=fontDlg.IsItalic();m_bBold=fontDlg.IsBold();m_bStrikeOut=fontDlg.IsStrikeOut();m_bUn
37、derline=fontDlg.IsUnderline();16 RedrawWindow();/重绘窗口(请求调用OnDraw)注意,不能让m_fontName=fontDlg.GetFaceName();,因为 m_fontName 为宽字符数组,而GetFaceName函数返回的是CString 对象。在 Ondraw 函数中设置字体并输出测试字符串:void CFontView:OnDraw(CDC*pDC)CFontDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);if(!pDoc)return;/TODO:在此处为本机数据添加绘制代码SetMyFo
38、nt(pDC,m_fontName,m_iFontSize,m_textColor,0,m_bItalic,m_bBold,m_bUnderline,m_bStrikeOut);pDC-TextOut(20,20,L测试字符串);图 9-5 为创建并使用字体的一般过程框图(粗体为核心步骤)。图 9-5 创建和使用字体的步骤定义字体对象CFont 创建公用字体对话框对象CFontDialog 打开公用字体对话框DoModal 创建初始字体CreatePointFont 获取逻辑字体结构GetLogFont 定义逻辑字体结构变量LOGFONT 初始化字体颜色m_cf.rgbColors 获取字体参
39、数GetFaceName、GetSize、GetColor、IsItalic、IsBold、IsUnderline、IsStrikeOut 删除原字体DeleteObject 创建字体CreatePointFont 或 CreateFont 选入字体SelectObject 获取 DC GetDC 绘制文本TextOut 等设置文本色SetTextColor 设置文本对齐SetTextAlign 释放 DC ReleaseDC 17 其中,粗体为核心步骤、点划线框部分对应于OnGetFont 函数、虚线框部分对应于SetMyFont 函数下面是一个利用SetMyFont函数来创建字体,并输出旋
40、转文本串的例子。其中,OnTextRotation 为菜单项ID_TEXT_ROTA TION 的事件处理函数,angle 为字符底线与水平线夹角的度数(注意,字体方向参数的单位为0.1 度)。void CFontView:OnTextRotation()CDC*pDC=GetDC();RECT rect;GetClientRect(&rect);CString sFontNum;wchar_t buf100;pDC-FillSolidRect(&rect,RGB(255,255,255);for(int angle=0;angle TextOut(rect.right/2,rect.bott
41、om/2,buf);ReleaseDC(pDC);输出结果如图9-6 所示。9.3 位图位图(bitmap)就是点阵图或光栅图,由像素阵列组成。鼠标的光标、工具条上的按钮、菜单项左边的图形标识、代表程序的图标、窗口标题条上的图 9-6 旋转文本输出18 最小化、最大化和关闭图案等都是典型的位图。位图可分成设备相关位图DDB 和设备无关位图 DIB,分别用于图像的显示和存储,对应的MFC 类分别为CBitmap 和 CImage,可利用这两个类各自的Attach 函数进行相互转换。9.3.1 颜色深度位图的每个像素用若干二进制位表示,二进制位的个数称为位图的颜色深度。常见的颜色深度及所能表示的颜
42、色数目见表9-5。表 9-5 颜色(位)数与颜色位图类型颜色位数颜色数颜色/位图类型1 21=2 索引色/伪彩图2 22=4 4 24=16 8 28=256 索引色/伪彩图或 直接色/灰度图15 215=32,768 直接色/真彩图(高彩图)16 216=65,536 24 224=16,777,216 直接色/真彩图(全彩图)低于或等于8 位(256 色)的位图,都为索引色,即像素的值不是颜色的基色强度,而只是调色板中的颜色表项的索引值(序号)。而高于或等于15 位(32,768 色)的位图,都为直接色,即像素的值是颜色的各基色强度,不需要调色板。9.3.2 DDB 与 DIB 设备相关位
43、图DDB 依赖于硬件的调色板,设备无关位图DIB 自己带有颜色信息,它们分别用于图像的显示和存储。1DDB DDB(Device Dependent Bitmap,设备相关位图)依赖于硬件的调色板,又叫 GDI 位图。有保存 DDB 位图参数的结构类型BITMAP:typedef struct tagBITMAP /bm LONG bmType;/类型,必须=0 19 LONG bmWidth;/宽度,像素个数,必须0 LONG bmHeight;/高度,像素个数,必须0 LONG bmWidthBytes;/每条扫描线(即每行像素)的字节数/必须能被2 整除(即每行字对齐,不足的位补0)WO
44、RD bmPlanes;/位面数=颜色深度WORD bmBitsPixel;/颜色深度LPVOID bmBits;/指向存放位图数据的字符(字节)数组的指针 BITMAP;2DIB DIB(Device Independent Bitmap,设备无关位图)带有自己的颜色信息,通常存储在BMP 文件中,直接由Win32 支持。DIB 所包含的图像信息主要有:颜色格式、分辨率、调色板和压缩标志。有若干对应的结构来描述这些信息,如BITMAPFILEHEADER、BITMAPINFO、BITMAPINFOHEADER。3DDB与 DIB DDB 与 DIB 是相关的,它们往往是同一幅图片的两种状态:
45、DDB 显示(显存)、DIB 存储(文件)。在 MFC 中 DDB 的功能被封装在CBitmap 类中,而DIB 的功能则被封装在CImage 类中,可通过各自的Attach 函数在它们二者之间进行相互转换。9.3.3 CBitmap类MFC 将 GDI 中的 DDB 位图封装进CBitmap 类,在该类中提供了对位图的操作。与 CPen、CBrush、CFont 等 GDI 对象一样,CBitmap 也是 CGdiObject 的派生类,参见图8-6。1成员函数表 9-6 CBitmap 类的成员函数成员函数说明20 构造函数CBitmap 构造 CBitmap 对象初始化LoadBitma
46、p 从资源装载位图LoadOEMBitmap 装载预定义位图LoadMappedBitmap 从资源装载位图,并将颜色映射到当前系统颜色CreateBitmap 创建具有指定高宽和图案的DDB 内存位图CreateBitmapIndirect 由 BITMAP 结构创建位图CreateCompatibleBitmap 创建与指定DC 兼容的位图CreateDiscardableBitmap 创建与指定DC 兼容的可废弃位图属性GetBitmap 获取位图的BITMAP结构operator HBITMAP 将 CBitmap 对象自动转换成HBITMAP指针的操作符操作FromHandle 由位
47、图指针HBITMAP构造 CBitmap 对象的静态函数SetBitmapBits 将指定的缓冲区的位图数据复制到CBitmap 中GetBitmapBits 将 CBitmap 中的位图数据复制到指定的缓冲区SetBitmapDimension 设置位图的高和宽(以0.1 毫米为单位)GetBitmapDimension 获取位图的高和宽(以0.1 毫米为单位)其中,默认构造函数CBitmap();只是简单地创建一个空的CBitmap 对象,该对象必须用位图装载或创建函数来初始化。其他常用的成员函数的原型有:BOOL LoadBitmap(UINT nIDResource);BOOL Cre
48、ateBitmap(int nWidth,int nHeight,UINT nPlanes,UINT nBitcount,const void*lpBits);BOOL CreateCompatibleBitmap(CDC*pDC,int nWidth,int nHeight);int GetBitmap(BITMAP*pBitMap);operator HBITMAP()const;staticCBitmap*PASCAL FromHandle(HBITMAP hBitmap);2使用 DDB位图使用 DDB 的主要步骤包括用LoadBitmap 函数装入位图资源及用BitBlt 函数显示图
49、片,DDB还可以用于创建图案刷和读显位图文件。1)装载位图资源可以用CBitmap 类的成员函数LoadBitmap 来装载位图资源:21 BOOL LoadBitmap(UINT nIDResource);其中,nIDResource 为位图资源ID,如(*.rc):IDB_LENA BITMAP DISCARDABLE “reslena.bmp”例如:CBitmap bmp;bmp.LoadBitmap(IDB_LENA);2)显示资源位图显示位图可使用CDC 类的成员函数BitBlt:BOOL BitBlt(int x,int y,int nWidth,int nHeight,CDC*p
50、SrcDC,int xSrc,int ySrc,DWORD dwRop);其中:x 与 y 为显示图像左上角的坐标。nWidth 与 nHeight 为图像的高与宽,可用CBitmap 的函数 GetBitmap 来获得pSrcDC 为源 DC,必须是兼容性DC,可用 CDC 的成员函数CreateCompatibleDC来转换:virtual BOOL CreateCompatibleDC(CDC*pDC);xSrc 与 ySrc 为源图像的左上角的坐标。dwRop 为光栅操作模式,可取值似SetROP2 函数,如:SRCCOPY(覆盖)、SRCAND(与)、SRCINVERT(异或)。下面