GDI+学习及代码总结之------文本与字体

WPF中GDI+图形图像的绘制:(一)绘制文本——动态设置字体、大小、颜色 GDI+(Graphics Device Interface Plus图形设备接口加)是.NET框架的重要组成部分,负责在屏幕和打印机上绘制图形图像和显示信息。GDI+不但在功能上比GDI 要强大很多,而且在代码编写方面也更简单,因此很快成为了Windows图形图像程序开发的首选。 从程序设计的角度看,GDI包括两部分:GDI对象和GDI函数。GDI对象定义了GDI函数使用的工具和环境变量;而G... 阅读详情

字体、字体系列基本概念与构造

字体系列

GDI+中将具有相同字样、包括不同风格的字体称为字体系列。字体从其系列中获得名称、重量(如粗体、规则、加亮)以及风格。例如Arial字体系列包含了下列4种字体:

Arial Regular(规则)、Arial Bold(黑体)、Arial Italic(斜体)、Arial Bold Italic(粗斜体);

在GDI+中输出文本之前,需要构造一个FontFamily对象和一个Font对象。FontFamily类的构造函数如下:

[cpp]  view plain copy
  1. FontFamily()   
  2. FontFamily(name, fontCollection)   
name:字体系列名。
fontCollection:指向一个FontCollection对象(字体集),表明字体系列所属的私有字体集,默认为NULL

示例(定义一个Arial Regular字体对象font)

[cpp]  view plain copy
  1. FontFamily fontFamily(L"Arial");  
  2. Font font(&fontFamily,16,FontStyleRegular,UnitPixel);  

看几个结构类型

1、LOGFONTA和LOGFONTW

两个都是一样的,只是一个用于ASCII编码,一个用于UNICODE编码


字体大小单位枚举(Unit)

[cpp]  view plain copy
  1. enum Unit{  
  2.   UnitWorld,//世界坐标,非物理上的单位  
  3.   UnitDisplay,//使用和输出设备相同的单位,如输出设备为显示器,其单位为像素  
  4.   UnitPixel,//像素  
  5.   UnitPoint,//点(磅),1点等于1/72英寸  
  6.   UnitInch,//英寸  
  7.   UnitDocument,//1/300英寸  
  8.   UnitMillimeter//毫米  
  9. };  
字体风格枚举(FontStyle)
[cpp]  view plain copy
  1. enum FontStyle{  
  2.   FontStyleRegular    = 0,//常规  
  3.   FontStyleBold       = 1,//加粗  
  4.   FontStyleItalic     = 2,//斜体  
  5.   FontStyleBoldItalic = 3,//粗斜  
  6.   FontStyleUnderline  = 4,//下划线  
  7.   FontStyleStrikeout  = 8//强调线,即在字体中部划线  
  8. };  
注意:在这几个样式中,常规、加粗、倾斜、粗斜不能同时使用。下划线和强调线风格可以同时使用,也就是说,字体风格由两部分组成,一部分与字体外形有关,另一部分是附加的线条风格(下划线和强调线),这两部分可以配合使用组成字体的整体风格。

例如,要描述一个带下划线和强调线的粗斜体风格的字体,可以使用下面的组合来完成:

[cpp]  view plain copy
  1. FontStyleBoldItalic |FontStyleUnderline |FontStyleStrikeout   
列举系统目前安装的字体信息

我们可以通过InstalledFontCollection类的成员函数GetFamilies枚举安装在计算机上的所有字体。GetFamilies函数返回的是一个FontFamily对象的数组。所以,在使用GetFamilies前,应该为FontFamily数组分配足够的内存空间。GetFamilies函数:

[cpp]  view plain copy
  1. Status GetFamilies(  
  2.   INT numSought,  
  3.   FontFamily* gpfamilies,  
  4.   INT* numFound  
  5. ) const;  
numSought:[in]字体集中的字体系列总数,通过InstalledFontCollection::GetFamilyCount()获取
gpfamilies:[out]存储返回的已安装的字体系列的数组;
numFound:[out]存储返回的字体系列总数,数值与numSought一样;

应用:列举出系统中的所有字体:

[cpp]  view plain copy
  1. SolidBrush solidbrush(Color::Black);  
  2. FontFamily fontfamily(L"Arial");  
  3. Font font(&fontfamily,8,FontStyleRegular,UnitPoint);  
  4.   
  5. int count=0;  
  6. int found=0;  
  7.   
  8. WCHAR familyName[100];//这里为了简化程序,分配足够大的空间  
  9. WCHAR *familyList=NULL;  
  10. FontFamily pFontFamily[500];//同样,分配足够大的空间  
  11.   
  12. CRect rect;  
  13. this->GetClientRect(&rect);  
  14. RectF r(0,0,rect.Width(),rect.Height());  
  15.   
  16. InstalledFontCollection installedFontCollection;  
  17. count=installedFontCollection.GetFamilyCount();  
  18. installedFontCollection.GetFamilies(count,pFontFamily,&found);  
  19.   
  20. familyList=new WCHAR[count*sizeof(familyName)];  
  21. wcscpy(familyList,L"");//先清空familyList,wcscpy实现对宽字节的复制操作  
  22. for(int j=0;j<count;j++){  
  23.     pFontFamily[j].GetFamilyName(familyName);  
  24.     wcscat(familyList,familyName);//把familyName添加到familyList的最后  
  25.     wcscat(familyList,L",");//wcscat实现对宽字节字符的添加操作  
  26. }  
  27. graphics.DrawString(familyList,-1,&font,r,NULL,&solidbrush);  
  28.   
  29. delete[] familyList;  

注意:wcscpy\wcscat函数分别实现了对双字节字符(宽字符)的复制、添加操作,在ASCII码中对应strcpy、strcat;

字体边沿平滑处理

大家都知道,当字体过大时,就会出现失真,边缘会出现锯齿,GDI+对字体边缘有一套自己的处理方式,是通过SetTextRenderingHint来实现的;

[cpp]  view plain copy
  1. Status SetTextRenderingHint(  
  2.   TextRenderingHint newMode  
  3. );  
其中TextRenderingHint是个枚举类,枚举了几种处理边缘的方式

[cpp]  view plain copy
  1. enum TextRenderingHint{  
  2.   TextRenderingHintSystemDefault = 0,//使用与系统相同的处理方式  
  3.   TextRenderingHintSingleBitPerPixelGridFit,//不消除锯齿,使用网格匹配  
  4.   TextRenderingHintSingleBitPerPixel,//不消除锯齿,不使用网格匹配  
  5.   TextRenderingHintAntiAliasGridFit,//消除锯齿,使用网格匹配  
  6.   TextRenderingHintAntiAlias,//消除锯齿,不使用网格匹配  
  7.   TextRenderingHintClearTypeGridFit //在液晶显示器上使用ClearType技术增强字体清晰度  
  8. };  
看示例:

[cpp]  view plain copy
  1. FontFamily fontfamily(L"宋体");  
  2. Font font(&fontfamily,60,FontStyleRegular,UnitPixel);  
  3.   
  4. //使用与系统相同的处理方式  
  5. graphics.SetTextRenderingHint(TextRenderingHintSystemDefault);  
  6. graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));  
  7.   
  8. //不消除锯齿,使用网格匹配  
  9. graphics.TranslateTransform(0,font.GetHeight(0.0f));  
  10. graphics.SetTextRenderingHint(TextRenderingHintSingleBitPerPixelGridFit );  
  11. graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));  
  12.   
  13. //不消除锯齿,不使用网格匹配  
  14. graphics.TranslateTransform(0,font.GetHeight(0.0f));  
  15. graphics.SetTextRenderingHint(TextRenderingHintSingleBitPerPixel );  
  16. graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));  
  17.   
  18. //消除锯齿,使用网格匹配  
  19. graphics.TranslateTransform(0,font.GetHeight(0.0f));  
  20. graphics.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit );  
  21. graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));  
  22.   
  23. //消除锯齿,不使用网格匹配  
  24. graphics.TranslateTransform(0,font.GetHeight(0.0f));  
  25. graphics.SetTextRenderingHint(TextRenderingHintAntiAlias );  
  26. graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));  
  27.   
  28. //在液晶显示器上使用ClearType技术增强字体清晰度  
  29. graphics.TranslateTransform(0,font.GetHeight(0.0f));  
  30. graphics.SetTextRenderingHint(TextRenderingHintClearTypeGridFit );  
  31. graphics.DrawString(L"什么玩意",-1,&font,PointF(0,0),&SolidBrush(Color::Green));  

从上面可以看出,列出的这六种边缘处理方式中,最后一种枚举成员TextRenderingHintClearTypeGridFit的处理效果最好。这种处理方式使用了Microsoft特有的ClearType技术。是专在液晶显示器上使用的一种增强字体清晰度的技术。但这种技术有时会出现问题,用投影仪投射到白色墙壁上,会出出字体显示不正常的情况,而且对于老式的CRT显示器是根本不支持的。操作系统也必须是XP及以上的系统才行。 所以一般用第一个参数,与系统处理方式相同就好。让系统决定我们适合哪种技术。

FontFamily和Font

在GDI+中输出文本之前,需要构造一个FontFamily对象和一个Font对象。FontFamily类的构造函数如下:

[cpp]  view plain copy
  1. FontFamily()   
  2. FontFamily(name, fontCollection)   
name:字体系列名。
fontCollection:指向一个FontCollection对象(字体集),表明字体系列所属的字体集,默认为NULL

再看看Font类的构造函数(先看这四个):

[cpp]  view plain copy
  1. Font(hdc)   
  2. Font(HDC hdc, LOGFONTA* logfont)   
  3. Font(HDC hdc, LOGFONTW* logfont)   
  4. Font(hdc, hfont)   
这四个都是GDI中的构造函数,这里就全不讲了,只说说最后两个纯正的GDI+中的Font构造函数

[cpp]  view plain copy
  1. Font(family, emSize, style, unit) ;//一般用这个  
  2. Font(familyName, emSize, style, unit, fontCollection) ;//当用到私有字体集时,才会用这个构造  

family、familyName:fontFamily对象
style:字体样式,是规则、粗体、斜体、粗斜体、下划线、强调线的枚举类,我们上面说过了
unit:字体大小
fontCollection:字体所属的字体集,这个是用来添加私有字体集的,下面我们将讲私有字体集。

构造私有字体集(PrivateFontCollection)

我们平时使用的字体集,只有在系统中注册过才能直接调用,但当我们使用一个别人系统中可能不存在的字体集时,我们可以从我们的字体文件中加载这个字体集,然后给用户使用,从文件中加载系统中没有注册的字体集的过程,就是创建私有字体集的过程。创建私有字体集用PrivateFontCollection类来实现,这里就不讲了,想了解的话,看《精通GDI+编程》P139。

Font的构造函数中的最后一个参数fontCollection就是从文件中加载的私有字体集;

字体尺寸、字体系列尺寸

字体尺寸和字体系统尺寸不是同一个概念,我们先看一下他们的共同部分,字体在几个距离上的概念:

几个概念:

基线:在英文中,会有基线的概念,这是个抽象的概念,所以GDI+并不支持对基线的设置,是指在四线格中的第三条线,这条线把字母分为上部和下部,如图中所示。

上部:是指从基线到上行字母顶部之间的距离。

下部:是从基线到下行字母底部的距离。

行距:是指上下两行基线之间的距离,包括基线之上的上部值、基线之下的下部值以及在上部之外的一些额外空间(通常用于形成行间距,对于这部分空间,GDI+也不提供函数直接访问操作。)

字体系列的尺寸(FontFamily)

字体系列尺寸,与实际显示的字体大小无关,它只与设计时的尺寸有关,获取函数有:

[cpp]  view plain copy
  1. FontFamily::GetEmHeight(style)//获取字体高度的设计单位;  
  2. FontFamily::GetCellAscent(style) //获取字体上部距离的设计单位数;  
  3. FontFamily::GetCellDescent(style)//获取字体下部距离的设计单位数;  
  4. FontFamily::GetLineSpacing(style)//获取行距的设计单位数;  
它们返回的并不是一个具体的物理尺寸,这些返回值并不被转换成具体的长度值。这些函数返回的只是一个抽像的大小,在GDI+中被称为设计单位(Desin Units)。对于一个设计单位,它的大小是固定的,它不会随着字体大小的改变而改变。从名称上就可以看出,设计单位是字体设计人员在设计字体时所使用的一种相对的坐标计量单位。
字体尺寸(Font)

字体尺寸是指在显示器上实际的尺寸(显示尺寸),它的操作函数的返回值与字体的大小成正比;获取函数有:

[cpp]  view plain copy
  1. Font::GetHeight(dpi)//获取字体高度,返回值以像素为单位;  
  2. Font::GetSize();//获取字体尺寸,返回值是em,1em=12dpi;1em称为1倍卡,对于倍卡的来义,参看《精通GDI+编程》P145  
虽然这里的API只提供了对字体高度值的获取,但我们可以通过计算得出上部显示高度,下部显示高度、行距;

看获取上部显示高度公式,其它都类似;

看代码示例:

[cpp]  view plain copy
  1. SolidBrush solidBrush(Color::Green);  
  2. PointF pointf(0.0f,0.0f);  
  3.   
  4. WCHAR infoString[100]=L"";  
  5. REAL FontHeightPixel;  
  6. UINT ascent;  
  7. REAL ascentPixel;  
  8. UINT desent;  
  9. REAL descentPixel;  
  10. UINT lineSpacing;  
  11. REAL lineSpacingPixel;  
  12.   
  13. FontFamily fontFamily(L"Arial");  
  14. Font font(&fontFamily,16,FontStyleRegular,UnitPixel);  
  15.   
  16. //显示字体显示大小  
  17. swprintf(infoString,L"使用font.GetSize()的返回值为:%.2fem;",font.GetSize());  
  18. graphics.DrawString(infoString,wcslen(infoString),&font,pointf,&solidBrush);  
  19. //获取字体显示高度  
  20. pointf.Y+=font.GetHeight(0.0);  
  21. swprintf(infoString,L"使用font.GetHeight()的返回值为:%.2f个像素",font.GetHeight(0.0));  
  22. graphics.DrawString(infoString,wcslen(infoString),&font,pointf,&solidBrush);  
  23. //获取字体设计高度  
  24. pointf.Y+=font.GetHeight(0.0);  
  25. swprintf(infoString,L"使用fontFamily.GetEmHeight()返回的字体高度为:%d个设计单位。",fontFamily.GetEmHeight(FontStyleRegular));  
  26. graphics.DrawString(infoString,-1,&font,pointf,&solidBrush);  
  27. //获取字体上部显示高度,----in 像素  
  28. pointf.Y+=2.0f*font.GetHeight(0.0f);  
  29. ascent=fontFamily.GetCellAscent(FontStyleRegular);  
  30. ascentPixel=font.GetSize()*ascent/fontFamily.GetEmHeight(FontStyleRegular);  
  31. swprintf(infoString,L"上部距离为%d个设计单位,%.2f像素。",ascent,ascentPixel);  
  32. graphics.DrawString(infoString,-1,&font,pointf,&solidBrush);  
  33. //获取字体下部显示高度---in 像素  
  34. pointf.Y+=font.GetHeight(0.0f);  
  35. desent=fontFamily.GetCellDescent(FontStyleRegular);  
  36. descentPixel=font.GetSize()*desent/fontFamily.GetEmHeight(FontStyleRegular);  
  37. swprintf(infoString,L"下部距离为%d个设计单位,%.2f像素。",desent,descentPixel);  
  38. graphics.DrawString(infoString,-1,&font,pointf,&solidBrush);  
  39. //获取显示行距,---in 像素  
  40. pointf.Y+=font.GetHeight(0.0f);  
  41. lineSpacing=fontFamily.GetLineSpacing(FontStyleRegular);  
  42. lineSpacingPixel=font.GetSize()*lineSpacing/fontFamily.GetEmHeight(FontStyleRegular);  
  43. swprintf(infoString,L"行距为%d个设计单位,%.2f像素。",lineSpacing,lineSpacingPixel);  
  44. graphics.DrawString(infoString,-1,&font,pointf,&solidBrush);  

注意:由于在中文中没有基线的概念,所以本节中提到的文本尺寸不一定适合中文。

写字

一、测量字符串显示宽度

在实际绘图中,有一个问题很值得我们考虑,我们怎么知道我们指定的RECT区域能否容得下我们要绘制的文字?如何确保我们的文字在所设置的区域内能够完整的显示?当然GDI+为我们提供了测量函数MeasureString,我们看下它的调用格式:

[cpp]  view plain copy
  1. MeasureString(string, length, font, layoutRect, boundingBox)   
  2. MeasureString(string, length, font, layoutRect, stringFormat, boundingBox, codepointsFitted, linesFilled)   
  3. MeasureString(string, length, font, layoutRectSize, stringFormat, size, codepointsFitted, linesFilled)   
  4. MeasureString(string, length, font, origin, boundingBox)   
  5. 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==0;

boundingBox.width=layoutRect.width;
boundingBox.height的值为在layoutRect.width;这个宽度上,要显示所有文字所需要的高度;

示例:

[cpp]  view plain copy
  1. WCHAR string[256]={0};  
  2. wcscpy(string,L"123456789abcdefg");  
  3. FontFamily fontfamily(L"Arial");  
  4.   
  5. Font font1(&fontfamily,30,FontStyleRegular,UnitPixel);  
  6. Font font2(&fontfamily,18,FontStyleRegular,UnitPixel);  
  7.   
  8. RectF layoutRect(10,10,130,0);//高度为0,让其自动计算高度  
  9. SolidBrush brush(Color::Green);  
  10. RectF boundRect;  
  11. INT codePointsFitted=0;  
  12. INT linesFitted=0;  
  13.   
  14. int strlen=wcslen(string);  
  15. graphics.MeasureString(string,strlen,&font1,layoutRect,NULL,&boundRect,&codePointsFitted,&linesFitted);  
  16. CString tmp;  
  17. CString s(string);  
  18. tmp.Format(L"欲输出的字符串为\n\"%s\"\n共%d个字符,\n其中,在规定的输出矩形中,\n只输出了%d行,共%d个字符",s,s.GetLength(),linesFitted,codePointsFitted);  
  19.   
  20. graphics.DrawRectangle(&Pen(Color::Red,2),layoutRect);  
  21. graphics.DrawRectangle(&Pen(Color::Red,2),boundRect);  
  22.   
  23. graphics.DrawString(string,-1,&font1,boundRect,NULL,&brush);  
  24. graphics.DrawString(tmp,-1,&font2,PointF(150,10),NULL,&brush);  

二、字符串去尾

字符串去尾,是指,当字符串在指定的RECT中无法全部显示时,如何去文本进行截取,以适应目标区域大小。我们暂时把这种截取操作称为“去尾”,去尾方式,是通过StringFormat类中的SetTrimming函数来设置的,其函数格式如下:

[cpp]  view plain copy
  1. Status SetTrimming(  
  2.   StringTrimming trimming  
  3. );  
其中StringTrimming是个枚举类,枚举了GDI+中所支持的去尾方式;

[cpp]  view plain copy
  1. enum StringTrimming{  
  2.   StringTrimmingNone      = 0,//不使用去尾  
  3.   StringTrimmingCharacter = 1,//以字符为单位去尾  
  4.   StringTrimmingWord      = 2,//以单词为单位去尾  
  5.   StringTrimmingEllipsisCharacter = 3,//以字符为单位去尾,略去部分使用省略号表示  
  6.   StringTrimmingEllipsisWord      = 4,//以单词为单位去尾,略去部分使用省略号表示  
  7.   StringTrimmingEllipsisPath      = 5//略去字符串中间部分,保证字符的首尾都能够显示  
  8. };  
看下他们的去尾效果(为保证效果,把字符串中的six去掉了):


使用方法,代码示例:

[cpp]  view plain copy
  1. SolidBrush solidBrush(Color::Green);  
  2. FontFamily fontFamily(L"宋体");  
  3. Font font(&fontFamily,25,FontStyleRegular,UnitPixel);  
  4.   
  5. Pen pen(Color::YellowGreen,2);  
  6. //为了看到效果,故意把six去掉了;  
  7. WCHAR text[]=L"one two three four five seven eight nine ten";  
  8.   
  9. StringFormat stringformat;  
  10. stringformat.SetTrimming(StringTrimmingCharacter);  
  11. graphics.DrawRectangle(&pen,10,30,200,60);  
  12. graphics.DrawString(text,-1,&font,RectF(10,30,200,60),&stringformat,&solidBrush);  

三、格式化文本输出(StringFormat类)

1、StringFormat::SetFormatFlags()

在使用DrawString函数输出文本时,可以控制文本输出的格式。这些输出格式包括文本对齐方式、文本的输出方向、文本是否自动换行、使用制表符定制文本列及文本是否剪裁等。这些操作都是使用StringFormat类实现的,先看它其中的一个比较重要的设置文本格式的函数:SetFormatFlags

[cpp]  view plain copy
  1. Status SetFormatFlags(  
  2.   INT flags  
  3. );  
其中flags是个枚举类(可以混合使用),枚举了几个格式用于设置,这里只讲解几个比较常用的,其它就不讲解了,如果需要可以查查相关资料;

[cpp]  view plain copy
  1. enum StringFormatFlags{  
  2.     StringFormatFlagsDirectionRightToLeft = 0x00000001,//从右至左输出文本  
  3.     StringFormatFlagsDirectionVertical = 0x00000002,//垂直方向输出文本  
  4.     StringFormatFlagsNoFitBlackBox = 0x00000004,  
  5.     StringFormatFlagsDisplayFormatControl = 0x00000020,  
  6.     StringFormatFlagsNoFontFallback = 0x00000400,  
  7.     StringFormatFlagsMeasureTrailingSpaces = 0x00000800,  
  8.     StringFormatFlagsNoWrap = 0x00001000,//输出时不使用自动换行功能  
  9.     StringFormatFlagsLineLimit = 0x00002000,  
  10.     StringFormatFlagsNoClip = 0x00004000//不使用裁剪  
  11. };  
看StringFormatFlagsDirectionRightToLeft和StringFormatFlagsDirectionVertical使用示例:

[cpp]  view plain copy
  1. CStringW temp(L"人生得意须尽欢,莫使金樽空对月!天生我材必有用,千金散尽还复来。");  
  2. FontFamily fontfamily(L"幼圆");  
  3. Font font(&fontfamily,20,FontStyleBold,UnitPixel);  
  4. SolidBrush brush(Color::Red);  
  5.   
  6. RectF f(10,10,120,font.GetHeight(0.0f)*8);  
  7. StringFormat strformat;  
  8. strformat.SetFormatFlags(StringFormatFlagsDirectionRightToLeft |StringFormatFlagsDirectionVertical );  
  9. strformat.SetAlignment(StringAlignmentCenter);  
  10. strformat.SetLineAlignment(StringAlignmentCenter);  
  11.   
  12. graphics.DrawRectangle(&Pen(Color::Green,2),f);  
  13. graphics.DrawString(temp,-1,&font,f,&strformat,&brush);  

StringFormatFlagsNoClip示例:

[cpp]  view plain copy
  1. CStringW temp(L"小白兔,白又白");  
  2. FontFamily fontfamily(L"幼圆");  
  3. Font font(&fontfamily,20,FontStyleBold,UnitPixel);  
  4. SolidBrush brush(Color::Red);  
  5. StringFormat strformat;  
  6. //使用默认,剪裁  
  7. graphics.DrawRectangle(&Pen(Color::Green,2),RectF(10,10,100,30));  
  8. graphics.DrawString(temp,-1,&font,RectF(10,10,100,30),&strformat,&brush);  
  9. //使用StringFormatFlagsNoClip标识,不剪裁  
  10. strformat.SetFormatFlags(StringFormatFlagsNoClip );  
  11. graphics.DrawRectangle(&Pen(Color::Green,2),RectF(120,10,100,30));  
  12. graphics.DrawString(temp,-1,&font,RectF(120,10,100,30),&strformat,&brush);  

2、设置文本对齐方式(StringFormat::SetAlignment(align))

提起“对齐”,大家可能会马上联想到“左对齐”、“右对齐”、“居中”之类的常用对齐方法。GDI+中通过stringFormat类下的下列两个成员函数来设置文本在水平和垂直方向上的对齐方式:

[cpp]  view plain copy
  1. StringFormat::SetAlignment(align)//设置水平对齐方式  
  2. StringFormat::SetLineAlignment(align)//设置垂直方向上的对齐方式  
其中align是StringAlignment枚举类中的成员:

[cpp]  view plain copy
  1. enum StringAlignment{  
  2.   StringAlignmentNear   = 0,//靠近,对水平对齐来言是居左对齐,对垂直而言是居上  
  3.   StringAlignmentCenter = 1,//靠中,对水平和垂直而言都是居中  
  4.   StringAlignmentFar    = 2//靠远,对水平而言是居右,对垂直而言是居下  
  5. };  
简单示例(水平居左,垂直居中):
[cpp]  view plain copy
  1. CStringW temp(L"小白兔");  
  2. FontFamily fontfamily(L"幼圆");  
  3. Font font(&fontfamily,20,FontStyleBold,UnitPixel);  
  4. SolidBrush brush(Color::Red);  
  5. StringFormat strformat;  
  6. strformat.SetAlignment(StringAlignmentNear);//水平居左  
  7. strformat.SetLineAlignment(StringAlignmentCenter );//垂直居中  
  8. graphics.DrawRectangle(&Pen(Color::Green,2),RectF(10,10,200,130));  
  9. graphics.DrawString(temp,-1,&font,RectF(10,10,200,130),&strformat,&brush);  


最终

由于构建DrawString时用的是brush,这就出现了有趣的地方,由于brush分为纯色画刷、影线画刷、纹理画刷、渐变画刷,所以我们可以用这几个画刷来写字,写出的字也具有了画刷所示的效果,这里就不再一一列举了,在《精通GDI+编程》中P178-P182演示了这几种画刷写字的示例,有兴趣的可以看看

DirectX学习笔记(十):3D字体的实现及用ID3DXFont接口绘制文本 1 阅读详情

相关推荐

【Win32绘图编程,GDI绘图对象】绘图基础,位图处理,绘图消息处理,画笔,画刷,文本绘制

这一篇文章分享本人学习win32绘图编程,其中包括GDI绘图对象,绘图基础,基本图形的绘制,画笔画刷的使用,文本绘制,以及文本字体的更改。

WdIg-2023的博客 2261

(文本平滑处理)TextRenderingHint文本呈现方式

GDI+学习及代码总结之------文本与字体

weixin_40333655的博客 979

gdi编程基础

一. DC 1. 概念 设备上下文:通俗来说就是,我们在绘图时用来响应软,硬件消息的媒介。MFC为我们封装了CDC类,那我们就结合MSDN来学习,就显得不会那么乱了。 2. CDC,CPaintDC, CClientDC, CWindowDC,CMetaFileDC CDC:DC的基类。 CPaintDC:跟进下源代码,发现本质上调用了BeginPaint()和E...

zhoumin4576的博客 3767

c#中Graphics常用的属性

在C#中,Graphics类是命名空间的一部分,它提供了用于绘制线条、形状和图像的方法。Graphics对象通常与Graphics类的FromImageFromHdcFromHwnd等方法一起使用,以获取用于绘制的Graphics对象。以下是一些GraphicsClip:获取或设置用于限定绘制区域的Region对象。:获取或设置绘图的合成模式。:获取或设置绘图的合成质量。:获取或设置插值模式,影响图像缩放时的图像质量。PageScale:获取或设置绘图时的缩放比例。PageUnit。

愿你历尽千帆,归来仍是少年。 3149

C#学习(十三)——C# 使用 GDI+ 画图

GDI - 图形设备接口(Graphics Device Interface) GDI是图形设备接口的英文缩写,主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形和图像输出。GDI的出现使程序员无需要关心硬件设备及设备正常驱动,就可以将应用程序的输出转化为硬件设备上的输出和构成,实现了程序开发者与硬件设备的隔离,大大方便了开发工作。 GDI是Graphics Device Interface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Wind

lvjiyang的博客 1830

[Gdiplus]_[中级]_[绘图实现单行文本的多种颜色]

场景 在使用 Gdiplus 绘制文本时, 偶尔会遇到需要支持绘制格式化文本的时候,而 Gdiplus 在这方面并不好,没有官方提供支持的类,也不支持 HTML 标签和 CSS 的样式. 而大部分提供这类富文本的绘制目前我所知道的一种就是通过 Web控件 来处理的. 比如调用 Chromium 的渲染实现. 另外一种实现就是通过实现自定义的富文本 RichText 控件, QQ 以前就是用...

小白 1409

C# 文字窗体

[System.Runtime.InteropServices.DllImport("gdi32")] private static extern IntPtr CreateFont(int H,int W,int E,int O,int FW,int I,int u,int S,int C,int OP,int CP,int Q,int PAF,string F); [System.

xiongxyt2的专栏 754

《GDI+高级编程》完整附书源代码

GDI+是Windows操作系统中用于图形和图像处理的一套编程接口(API),它是在GDI(图形设备接口)的基础上发展起来的。GDI最早出现在Windows 3.0版本中,而GDI+则首次出现在Windows XP中,并在后续的Windows版本中得到了不断的增强和优化。GDI+ 提供了强大的绘图功能,但有时候我们需要更特殊的绘图效果。自定义绘图可以通过继承特定的绘图类并重写绘图方法来实现。例如,继承类并重写方法,可以创建独特的渐变效果。

weixin_29041443的博客 317

[学习笔记] Windows编程——GDI——(八)字体和文本

学习笔记,随时更新。如有谬误,欢迎指正。说明:红色字体。

cxsydzn的博客 1208

C#文本处理与图形绘制综合实例教程

有时用户可能需要在同一个界面中看到不同大小的文本,以突出显示某些信息或为了视觉美观。这就需要我们对特定控件进行字体大小的自定义。这通常通过继承原有控件并重写其OnRender方法实现,在此方法中可以指定特定的Font属性。// 自定义字体大小// 示例字号以上内容展示了调整字体字号的技术,涵盖了字体大小的影响因素、动态调整和全局/局部设置的实现方法,以及它们对用户体验的影响。在下一章节中,我们将继续探讨在用户界面中绘制文字的应用实例,展示如何将这些技术应用于实际项目中。

weixin_42513928的博客 430

深入理解GDI+中的颜色、字体和文本处理

本篇博客深入解析了.NET Framework中GDI+的使用,特别是颜色、字体和文本的表示和处理。涵盖了从基本的颜色ARGB模式到复杂的文本转换操作,同时介绍了系统颜色的使用以及如何在应用程序中实现这些图形元素。

weixin_42466723的博客 430

GDI+ 文本格式化设置

GDI+ 文本格式化设置

编程猿来如此 1455

GDI+ 高级编程技巧与实践

GDI+(图形设备接口+)是微软公司提供的一套用于在Windows操作系统上进行二维矢量图形、光栅图形、文字和图像处理的API。它是GDI(图形设备接口)的改进版本,提供了更丰富的功能和更好的性能。GDI+作为.NET Framework的一部分,为开发者提供了一种强大的方式来创建和显示图形和图像。Graphics类是.NET框架中用于绘制图形、处理图像和打印输出的核心类,它为GDI+提供了一个绘图界面。

weixin_35257663的博客 818

WindowsAPI学习笔记三 - 字体设置与输出

Windows系统中经常使用GDI进行文本输出从某种意义上来说图形和文本并没有本质上的界限很多时候windows把文本也当作图形对待。在windows编程中文本操作首先要获得文本句柄此外还要设置字体字符大小字符颜色等有关属性并将它们选入设备环境。设置文本的设备环境1.自定义字体可以使用函数CreateFont自定义...

weixin_34138255的博客 1788

Matlab生成dsp程序——环境搭建(c2000系列[F28335、F2837x]都适用)

一、环境配置 (28377D的操作是一模一样就是硬件设置的时候需要选择28377d进行相应的设置) 1)matlab与ccs联合编译需要安装对应的matlab版本和ccs版本,且只有2016a以上的matlab支持c2000系列。具体对应关系参照: http://software-dl.ti.com/ccs/esd/documents/ccs_matlab.html 2)matlab版本确定之后,还需要安装有关于ccs的相关软件: I、TI Code Composer Studio xxxx(对应

qq_42151264的博客 2万+

从踩坑到填平:我在RHEL7上给Tesla A100装驱动的完整记录(含Fabric Manager配置)

本文详细记录了在RHEL7系统上为Tesla A100安装Nvidia驱动的完整过程,包括Fabric Manager配置的关键步骤。通过分析A100架构的特殊性,提供了从驱动安装到服务配置的详细指南,并分享了常见问题的排查方法和性能调优技巧,帮助用户高效部署高性能GPU计算环境。

weixin_29291863的博客 283
上一篇: GDI+学习及代码总结之-----画笔
下一篇: GDI+学习及代码总结之------区域
htt9931
博客等级 码龄24年 43粉丝 14原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值