GDI+学习及代码总结之-文本与字体_第1页
GDI+学习及代码总结之-文本与字体_第2页
GDI+学习及代码总结之-文本与字体_第3页
GDI+学习及代码总结之-文本与字体_第4页
GDI+学习及代码总结之-文本与字体_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

GDI+学习及代码总结之文本与字体字体系列GDI+中将具有相同字样、包括不同风格的字体称为字体系列。字体从其系列中获得名称、重量(如粗体、规则、加亮)以及风格。例如Arial字体系列包含了下列4种字体:ArialRegular(规则)、ArialBold(黑体)、ArialItalic(斜体)、ArialBoldItalic(粗斜体);在GDI+中输出文本之前,需要构造一个FontFamily对象和一个Font对象。FontFamily类的构造函数如下:FontFamily()FontFamily(name,fontCollection)name:字体系列名。fontCollection:指向一个FontCollection对象(字体集),表明字体系列所属的私有字体集,默认为NULL示例(定义一个ArialRegular字体对象font)FontFamilyfontFamilyFontFamilyfontFamily();Fontfont(&fontFamily,16,FontStyleRegular,UnitPixel);看几个结构类型1、LOGFONTA和LOGFONTW两个都是一样的,只是一个用于ASCII编码,一个用于UNICODE编码字体大小单位枚举(Unit)如输岀设备为显示器,其单位为像素enumlUnit{如输岀设备为显示器,其单位为像素UnitDisplay,//使用和输岀设备相同的单位,UnitPixel,//像素UnitPoint,〃点(磅),2点等于1/72英寸UnitInch,//英寸UnitDocumen弋J/1/300英寸UnitMillimeter//毫米};字体风格枚举(FontStyle)enumFontStyle{FontStyleRegular=0,//常规FontStyleBold=1,//加粗FontStyleltalic=2,//斜体FontStyleBoldItalic=3,//粗斜FontStyleUnderline=4,//下划线FontStyleStrikeout=8//强调线,即在字体中部划线};注意:在这几个样式中,常规、加粗、倾斜、粗斜不能同时使用。下划线和强调线风格可以同时使用,也就是说,字体风格由两部分组成,一部分与字体外形有关,另一部分是附加的线条风格(下划线和强调线),这两部分可以配合使用组成字体的整体风格。例如,要描述一个带下划线和强调线的粗斜体风格的字体,可以使用下面的组合来完成:FontStyleBoldItalicFontStyleUnderlineFontStyleStrikeout列举系统目前安装的字体信息我们可以通过InstalledFontCollection类的成员函数GetFamilies枚举安装在计算机上的所有字体。GetFamilies函数返回的是一个FontFamily对象的数组。所以,在使用GetFamilies前,应该为FontFamily数组分配足够的内存空间。GetFamilies函数:StatusGetFamilies(INTnumSought,FontFamily*gpfamilies,INT*numFound)const;numSought:[in]字体集中的字体系列总数,通过InstalledFontCollection::GetFamilyCount()获取gpfamilies:[out]存储返回的已安装的字体系列的数组;numFound:[out]存储返回的字体系列总数,数值与numSought一样;应用:列举出系统中的所有字体:SolidBrushsolidbrush(Color::Black);FontFamilyfontfamily(L"Arial");Fontfont(&fontfamily,8,FontStyleRegular,UnitPoint);intcount=0;intfound=0;WCHARfamilyName[100];//这里为了简化程序,分配足够大的空间WCHAR*familyList=NULL;FontFamilypFontFamily[500];//同样,分配足够大的空间CRectrect;this->GetClientRect(&rect);RectFr(0,0,rect.Width(),rect.Height());InstalledFontCollectioninstalledFontCollection;count=installedFontCollection.GetFamilyCount();installedFontCollection.GetFamilies(count,pFontFamily,&found);familyList=newWCHAR[count*sizeof(familyName)];wcscpy(familyList,L"");//先清空famiLyList,wcscpy实现对宽字节的复制操作for(intj=0;j<count;j++){pFontFamily[j].GetFamilyName(familyName);wcscat(familyList,familyName);//把familyName添加到familyList的最后wcscat(familyList,L",");//wcscat实现对宽字节字符的添加操作}graphics.DrawString(familyList,-1,&font,r,NULL,&solidbrush);delete[]familyList;注意:wcscpy'wcscat函数分别实现了对双字节字符(宽字符)的复制、添加操作,在ASCII码中对应strcpy、strcat;字体边沿平滑处理大家都知道,当字体过大时,就会出现失真,边缘会出现锯齿,GDI+对字体边缘有一套自己的处理方式,是通过SetTextRenderingHint来实现的;StatusSetTextRenderingHint(TextRenderingHintnewMode);其中TextRenderingHint是个枚举类,枚举了几种处理边缘的方式enumTextRenderingHint{TextRenderingHintSystemDefault=0,//使用与系统相同的处理方式TextRenderingHintSingleBitPerPixelGridFit,//不消除锯齿,使用网格匹配TextRenderingHintSingleBitPerPixel,//不消除锯齿,不使用网格匹配TextRenderingHintAntiAliasGridFit,//消除锯齿,使用网格匹配TextRenderingHintAntiAlias,//消除锯齿,不使用网格匹配TextRenderingHintClearTypeGridFit〃在液晶显示器上使用ClearType技术增强字体清晰度};看示例:FontFamilyfontfamily(L"宋体”);Fontfont(&fontfamily,60,FontStyleRegular,UnitPixel);//使用与系统相同的处理方式graphics.SetTextRenderingHint(TextRenderingHintSystemDefault);graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));〃不消除锯齿,使用网格匹配graphics.TranslateTransform(0,font.GetHeight(0.0f));graphics.SetTextRenderingHint(TextRenderingHintSingleBitPerPixelGridFit);graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));〃不消除锯齿,不使用网格匹配graphics.TranslateTransform(0,font.GetHeight(0.0f));graphics.SetTextRenderingHint(TextRenderingHintSingleBitPerPixel);graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));〃消除锯齿,使用网格匹配graphics.TranslateTransform(0,font.GetHeight(0.0f));graphics.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));〃消除锯齿,不使用网格匹配graphics.TranslateTransform(0,font.GetHeight(0.0f));graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));〃在液晶显示器上使用ClearType技术增强字体清晰度graphics.TranslateTransform(0,font.GetHeight(0.0f));graphics.SetTextRenderingHint(TextRenderingHintClearTypeGridFit);graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));从上面可以看出,列出的这六种边缘处理方式中,最后一种枚举成员TextRenderingHintClearTypeGridFit的处理效果最好。这种处理方式使用了Microsoft特有的ClearType技术。是专在液晶显示器上使用的一种增强字体清晰度的技术。但这种技术有时会出现问题,用投影仪投射到白色墙壁上,会出出字体显示不正常的情况,而且对于老式的CRT显示器是根本不支持的。操作系统也必须是XP及以上的系统才行。所以一般用第一个参数,与系统处理方式相同就好。让系统决定我们适合哪种技术。FontFamily和Font在GDI+中输出文本之前,需要构造一个FontFamily对象和一个Font对象。FontFamily类的构造函数如下:FontFamily()FontFamily(name,fontCollection)name:字体系列名。fontCollection:指向一个FontCollection对象(字体集),表明字体系列所属的字体集,默认为NULL再看看Font类的构造函数(先看这四个):IFont(hdc)Font(HDChdc,LOGFONTA*logfont)Font(HDChdc,LOGFONTW*logfont)Font(hdc,hfont)这四个都是GDI中的构造函数,这里就全不讲了,只说说最后两个纯正的GDI+中的Font构造函数Font(family,emSize,style,unit);〃一般用这个Font(familyName,emSize,style,unit,fontCollection)〃当用到私有字体时,才会用这个构造family、familyName:fontFamily对象style:字体样式,是规则、粗体、斜体、粗斜体、下划线、强调线的枚举类,我们上面说过了unit:字体大小fontCollection:字体所属的字体集,这个是用来添加私有字体集的,下面我们将讲私有字体集。构造私有字体集(PrivateFontCollection)我们平时使用的字体集,只有在系统中注册过才能直接调用,但当我们使用一个别人系统中可能不存在的字体集时,我们可以从我们的字体文件中加载这个字体集,然后给用户使用,从文件中加载系统中没有注册的字体集的过程,就是创建私有字体集的过程。创建私有字体集用PrivateFontCollection类来实现,这里就不讲了,想了解的话,看《精通GDI+编程》P139。Font的构造函数中的最后一个参数fontCollection就是从文件中加载的私有字体集;字体尺寸、字体系列尺寸字体尺寸和字体系统尺寸不是同一个概念,我们先看一下他们的共同部分,字体几个概念:基线:在英文中,会有基线的概念,这是个抽象的概念,所以GDI+并不支持对基线的设置,是指在四线格中的第三条线,这条线把字母分为上部和下部,如图中所示。上部:是指从基线到上行字母顶部之间的距离。下部:是从基线到下行字母底部的距离。行距:是指上下两行基线之间的距离,包括基线之上的上部值、基线之下的下部值以及在上部之外的一些额外空间(通常用于形成行间距,对于这部分空间,GDI+也不提供函数直接访问操作。)字体系列的尺寸(FontFamily)字体系列尺寸,与实际显示的字体大小无关,它只与设计时的尺寸有关,获取函数有:FontFamily::GetEmHeight(style)//获取字体高度的设计单位;FontFamily::GetCellAscent(style)//获取字体上部距离的设计单位数;FontFamily::GetCellDescent(style)//获取字体下部距离的设计单位数;FontFamily::GetLineSpacing(style)//获取行距的设计单位数;它们返回的并不是一个具体的物理尺寸,这些返回值并不被转换成具体的长度值。这些函数返回的只是一个抽像的大小,在GDI+中被称为设计单位(DesinUnits)。对于一个设计单位,它的大小是固定的,它不会随着字体大小的改变而改变。从名称上就可以看出,设计单位是字体设计人员在设计字体时所使用的一种相对的坐标计量单位。字体尺寸(Font)字体尺寸是指在显示器上实际的尺寸(显示尺寸),它的操作函数的返回值与字体的大小成正比;获取函数有:Font::GetHeight(dpi)//获取字体高度,返回值以像素为单位;Font::GetSize();〃获取字体尺寸,返回值是加,1em=12dpi;1em称为1倍卡,对于倍卡的来义,参看《精通GDI+编程》P145虽然这里的API只提供了对字体高度值的获取,但我们可以通过计算得出上部显示高度,下部显示高度、行距;看获取上部显示高度公式,其它都类似;看代码示例:SolidBrushsolidBrush(Color::Green);PointFpointf(0.0f,0.0f);WCHARinfoString[100]=L"";REALFontHeightPixel;UINTascent;REALascentPixel;UINTdesent;REALdescentPixel;UINTlineSpacing;REALlineSpacingPixel;FontFamilyfontFamily(L"Arial");Fontfont(&fontFamily,16,FontStyleRegular,UnitPixel);〃显示字体显示大小swprintf(infoString,L"使用font.GetSize()的返回值为:%.2fem;",font.GetSize());graphics.DrawString(infoString,wcslen(infoString),&font,pointf,&solidBrush);〃获取字体显示高度pointf.Y+=font.GetHeight(0.0);swprintf(infoString,L"使用font.GetHeight()的返回值为:%.2f个像素"font.GetHeight(0.0));graphics.DrawString(infoString,wcslen(infoString),&font,pointf,&solidBrush);〃获取字体设计高度pointf.Y+=font.GetHeight(0.0);swprintf(infoString,L"使用fontFamily.GetEmHeight()返回的字体高度为:%d个设计单位。",fontFamily.GetEmHeight(FontStyleRegular));graphics.DrawString(infoString,-1,&font,pointf,&solidBrush);〃获取字体上部显示高度,——in像素pointf.Y+=2.0f*font.GetHeight(0.0f);ascent=fontFamily.GetCellAscent(FontStyleRegular);ascentPixel=font.GetSize()*ascent/fontFamily.GetEmHeight(FontStyleRegular);swprintf(infoString,L"上部距离%%d个设计单位,%.2f像素。",ascent,ascentPixel);graphics.DrawString(infoString,-1,&font,pointf,&solidBrush);〃获取字体下部显示高度--in像素pointf.Y+=font.GetHeight(0.0f);desent=fontFamily.GetCellDescent(FontStyleRegular);descentPixel=font.GetSize()*desent/fontFamily.GetEmHeight(FontStyleRegular);swprintf(infoString,L"下部距离为%d个设计单位,%.2f像素。",desent,descentPixel);graphics.DrawString(infoString,-1,&font,pointf,&solidBrush);//获取显示行距,---in像素pointf.Y+=font.GetHeight(0.0f);lineSpacing=fontFamily.GetLineSpacing(FontStyleRegular);lineSpacingPixel=font.GetSize()*lineSpacing/fontFamily.GetEmHeight(FontStyleRegular);swprintf(infoString,L"行距为%d个设计单位,%.2f像素。",lineSpacing,lineSpacingPixel);graphics.DrawString(infoString,-1,&font,pointf,&solidBrush);注意:由于在中文中没有基线的概念,所以本节中提到的文本尺寸不一定适合中文。一、测量字符串显示宽度在实际绘图中,有一个问题很值得我们考虑,我们怎么知道我们指定的RECT区域能否容得下我们要绘制的文字?如何确保我们的文字在所设置的区域内能够完整的显示?当然GDI+为我们提供了测量函数MeasureString,我们看下它的调用格式:Measurestring(string,length,font,layoutRect,boundingBox)Measurestring(string,length,font,layoutRect,stringFormat,boundingBox,codepointsFitted,linesFilled)MeasureString(string,length,font,layoutRectSize,stringFormat,size,codepointsFitted,linesFilled)MeasureString(string,length,font,origin,boundingBox)MeasureString(string,length,font,origin,stringFormat,boundingBox)参数说明:string:[in]所在绘制的字符串length:[in]字符串里字符个数,-1表示字符串以空白结尾。font:[in]字符串输出时使用的字体;origin:[in]输出原点stringFormat:[in]输出所用格式;layoutRect、layoutRectSize:[in]指定的文本输出区域boundingBox、size:[out]计算后的文本输出的限制矩形(注意中详细讲解)linesFilled:[out]计算出的在指定区域中能够显示的字符行数;codepointsFitted:[out]计算出的在指定区域中能够显示的字符个数;注意:boundingBox的计算法则:1、当layoutRect的width、height都不为0时;boundingBox的值是输出文本所需要的区域与layoutRect的区域的交集,也就是说,在这种情况下,boundingBox的值始终小于等于layoutRect的值;2、当layoutRect的width为0时,height!=0;boundingBox.height=layoutRect.height;boundingBox.width的值为在layoutRect.height;这个高度上,要显示所有文字所需要的宽度;3、当layoutRect的width!=0,height==O;boundingBox.width=layoutRect.width;boundingBox.height的值为在layoutRect.width;这个宽度上,要显示所有文字所需要的高度;示例:WCHARstring[256]={0};wcscpy(string,L"123456789abcdefg");FontFamilyfontfamily(L"Arial");Fontfont1(&fontfamily,30,FontStyleRegular,UnitPixel);Fontfont2(&fontfamily,18,FontStyleRegular,UnitPixel);RectFlayoutRect(10,10,130,0);//高度为0,让其自动计算高度SolidBrushbrush(Color::Green);RectFboundRect;INTcodePointsFitted=0;INTlinesFitted=0;intstrlen=wcslen(string);graphics.MeasureString(string,strlen,&font1,layoutRect,NULL,&boundRect,&codePointsFitted,&linesFitted);CStringtmp;CStrings(string);tmp.Format(L"欲输出的字符串为\n\"%s\"\n共%d个字符,\n其中,在规定的输出矩形中,\n只输出了%d行,共%d个字符s,s.GetLength(),linesFitted,codePointsFitted);graphics.DrawRectangle(&Pen(Color::Red,2),layoutRect);graphics.DrawRectangle(&Pen(Color::Red,2),boundRect);graphics.DrawString(string,-1,&font1,boundRect,NULL,&brush);graphics.DrawString(tmp,-1,&font2,PointF(150,10),NULL,&brush);二、字符串去尾字符串去尾,是指,当字符串在指定的RECT中无法全部显示时,如何去文本进行截取,以适应目标区域大小。我们暂时把这种截取操作称为“去尾”,去尾方式,是通过StringFormat类中的SetTrimming函数来设置的,其函数格式如下:StatusSetTrimming(StringTrimmingtrimming);其中StringTrimming是个枚举类,枚举了GDI+中所支持的去尾方式;enumStringTrimming{StringTrimmingNone=0,//不使用去尾StringTrimmingCharacter=1,//以字符为单位去尾

StringTrimmingWordStringTrimmingEllipsisCharacter表示StringTrimmingEllipsisWordStringTrimmingWordStringTrimmingEllipsisCharacter表示StringTrimmingEllipsisWord表示StringTrimmingEllipsisPath能够显示};=2,//以单词为单位去尾=3,//以字符为单位去尾略去部分使用省略=4,//以单词为单位去尾略去部分使用省略=5//略去字符串中间部分,保证字符的首尾看下他们的去尾效果(为保证效果,把字符串中的six去掉了):□使用方法,代码示例:SolidBrushsolidBrush(Color::Green);FontFamilyfontFamily(L"宋体");Fontfont(&fontFamily,25,FontStyleRegular,UnitPixel);Penpen(Color::YellowGreen,2);//为了看到效果,故意抵认去掉了;WCHARtext[]=L"onetwothreefourfiveseveneightnineten";StringFormatstringformat;stringformat.SetTrimming(StringTrimmingCharacter);graphics.DrawRectangle(&pen,10,30,200,60);graphics.DrawString(text,-1,&font,RectF(10,30,200,60),&stringformat,&solidBrush);三、格式化文本输出(StringFormat类)1、StringFormat::SetFormatFlags()在使用DrawString函数输出文本时,可以控制文本输出的格式。这些输出格式包括文本对齐方式、文本的输出方向、文本是否自动换行、使用制表符定制文本列及文本是否剪裁等。这些操作都是使用StringFormat类实现的,先看它其中的一个比较重要的设置文本格式的函数:SetFormatFlagsStatusSetFormatFlags(INTflags);其中flags是个枚举类(可以混合使用),枚举了几个格式用于设置,这里只讲解几个比较常用的,其它就不讲解了,如果需要可以查查相关资料;enumlStringFormatFlags{StringFormatFlagsDirectionRightToLeft=0x00000001,//从右至左输岀文本StringFormatFlagsDirectionVertical=0x00000002,//垂直方向输岀文本StringFormatFlagsNoFitBlackBox=0x00000004,StringFormatFlagsDisplayFormatControl=0x00000020,StringFormatFlagsNoFontFallback=0x00000400,StringFormatFlagsMeasureTrailingSpaces=0x00000800,StringFormatFlagsNoWrap=0x00001000,//输岀时不使用自动换行功能StringFormatFlagsLineLimit=0x00002000,StringFormatFlagsNoClip=0x00004000'/不使用裁剪};看StringFormatFlagsDirectionRightToLeft和StringFormatFlagsDirectionVertical使用示例:CStringWtemp(L"人生得意须尽欢,莫使金樽空对月!天生我材必有用,千金散尽还复来。”);FontFamilyfontfamily(L"幼圆”);Fontfont(&fontfamily,20,FontStyleBold,UnitPixel);SolidBrushbrush(Color::Red);RectFf(10,10,120,font.GetHeight(0.0f)*8);StringFormatstrformat;strformat.SetFormatFlags(StringFormatFlagsDirectionRightToLeft|StringFormatFlagsDirectionVertical);strformat.SetAlignment(StringAlignmentCenter);strformat.SetLineAlignment(StringAlignmentCenter);graphics.DrawRectangle(&Pen(Color::Green,2),f);graphics.DrawString(temp,-1,&font,f,&strformat,&brush);StringFormatFlagsNoClip示例:CStringWtemp(L"小白兔,白又白");FontFamilyfontfamily(L"幼圆");Fontfont(&fontfamily,20,FontStyleBold,UnitPixel);SolidBrushbru

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论