在使用GDI方式处理文本时,往往会用到StringFormat。里面的某些点有点反直觉,不够直观,所以本篇就通过图文的方式去讲解一下。

本篇内容仅涉及到文本方向、对齐的相关内容。

如有错误、不妥之处,欢迎大家指正。

一、相关属性

与文本方向、对齐相关的属性,主要与三个属性有关:

Alignment、LineAlignment、FormatFlags。

Alignment与LineAlignment的属性值都是StringAlignment枚举。StringAlignment枚举有三个成员:Near、Center、Far。其MSDN解释如下:

FormatFlags的属性值是StringFormatFlags枚举。主要与其枚举的两个成员——DirectionRightToLeft、DirectionVertical——有关。其MSDN解释如下:

二、使用搭配

1,现代文的阅读顺序:水平方向上从左到右、从上到下。

此时,FormatFlags不包含成员DirectionRightToLeft、DirectionVertical。

1.1,对于Alignment,其示意图如下:

此时,StringAlignment枚举的三个成员——Near、Center、Far——可以理解为:

Near:左对齐

Center:居中对齐

Far:右对齐

1.2,对于LineAlignment,其示意图如下:

此时,StringAlignment枚举的三个成员——Near、Center、Far——可以理解为:

Near:文本段落处于显示区域顶部

Center:文本段落处于显示区域中部

Far:文本段落处理显示区域底部

1.3,Alignment和LineAlignment的组合共有9种,如下所示:

2,古文的阅读顺序:垂直方向上从上到下、从右到左。

此时,FormatFlags同时包含成员DirectionRightToLeft、DirectionVertical。

2.1,对于Alignment,其示意图如下:

此时,StringAlignment枚举的三个成员——Near、Center、Far——可以理解为:

Near:顶部对齐

Center:居中对齐

Far:底部对齐

2.2,对于LineAlignment,其示意图如下:

此时,StringAlignment枚举的三个成员——Near、Center、Far——可以理解为:

Near:文本段落处于显示区域右侧

Center:文本段落处于显示区域中侧

Far:文本段落处理显示区域左侧

2.3,Alignment和LineAlignment的组合共有9种,如下所示:

3,其他

除上文两种搭配方式之外,还有两种搭配方式,即分别使用DirectionRightToLeft和DirectionVertical,这两种搭配方式共有18种样式,不过日常几乎用不到。具体想查看可以通过文末提供的示例源代码自行查看。

示例程序截图:

三、重点说明

仅搭配使用而言,并没有什么可多说的,直接使用即可,但是如果想在某个具体的区域内显示文本段落的话——比如上面的示例截图,其坐标的计算是个难点。

这里的“坐标”并不是人眼看上去的坐标,而是使用Graphics.DrawString时所使用的坐标——绘制文本的左上角。

下面进行举例说明。

例1,现代文方式、右对齐、居中显示。

示意图如下所示(这个示意图是用GDI画的,其中绿框是后期为了方便讲解而手动加的):

其中:

显示区域(上图的蓝色方框):宽=高=200

文本区域:即字符串所占的矩形区域(上图中绿色方框):宽:165,高:43

此时,在使用DrawString时,其point(绘制文本的左上角)的坐标并不是绿色方框的左上角:X:200-165=35,Y:(200-43)/2=78(此处取整数)

其坐标应该是:X:200,Y:200/2=100,即下图中红点所在的坐标(其中黄线是中线):

是不是很反直觉?

不过当接受了这种坐标计算思路之后,一切就迎刃而解了。

下面再举一个例子:

例2:古文方式、底部对齐、左侧显示

示意图如下所示(这个示意图是用GDI画的,其中绿框是后期为了方便讲解而手动加的):

其中:

显示区域(上图的蓝色方框):宽=高=200

文本区域:即字符串所占的矩形区域(上图中绿色方框):宽:43,高:165

此时,在使用DrawString时,其point(绘制文本的左上角)的坐标并不是绿色方框的左上角:X:0,Y:200-165=35

其坐标应该是:X:0,Y:200,即下图中红点所在的坐标:

四、坐标计算核心代码

完整代码见下方提供的源工程。

 //……

 Bitmap bmpStr = new Bitmap(,);
PointF stringStart = new PointF(, ); if (!DirectionRightToLeft)
{
if (!DirectionVertical)
{
if (alignment == StringAlignment.Near)
{
stringStart.X = ;
}
else if (alignment == StringAlignment.Center)
{
stringStart.X = bmpStr.Width / ;
}
else if (alignment == StringAlignment.Far)
{
stringStart.X = bmpStr.Width;
} if (lineAlignment == StringAlignment.Near)
{
stringStart.Y = ;
}
else if (lineAlignment == StringAlignment.Center)
{
stringStart.Y = bmpStr.Height / ;
}
else if (lineAlignment == StringAlignment.Far)
{
stringStart.Y = bmpStr.Height;
}
}
else
{
if (alignment == StringAlignment.Near)
{
stringStart.Y = ;
}
else if (alignment == StringAlignment.Center)
{
stringStart.Y = bmpStr.Height / ;
}
else if (alignment == StringAlignment.Far)
{
stringStart.Y = bmpStr.Height;
} if (lineAlignment == StringAlignment.Near)
{
stringStart.X = ;
}
else if (lineAlignment == StringAlignment.Center)
{
stringStart.X = bmpStr.Width / ;
}
else if (lineAlignment == StringAlignment.Far)
{
stringStart.X = bmpStr.Width;
}
}
}
else
{
if (!DirectionVertical)
{
if (alignment == StringAlignment.Near)
{
stringStart.X = bmpStr.Width;
}
else if (alignment == StringAlignment.Center)
{
stringStart.X = bmpStr.Width / ;
}
else if (alignment == StringAlignment.Far)
{
stringStart.X = ;
} if (lineAlignment == StringAlignment.Near)
{
stringStart.Y = ;
}
else if (lineAlignment == StringAlignment.Center)
{
stringStart.Y = bmpStr.Height / ;
}
else if (lineAlignment == StringAlignment.Far)
{
stringStart.Y = bmpStr.Height;
}
}
else
{
if (alignment == StringAlignment.Near)
{
stringStart.Y = ;
}
else if (alignment == StringAlignment.Center)
{
stringStart.Y = bmpStr.Height / ;
}
else if (alignment == StringAlignment.Far)
{
stringStart.Y = bmpStr.Height;
} if (lineAlignment == StringAlignment.Near)
{
stringStart.X = bmpStr.Width;
}
else if (lineAlignment == StringAlignment.Center)
{
stringStart.X = bmpStr.Width / ;
}
else if (lineAlignment == StringAlignment.Far)
{
stringStart.X = ;
}
}
} //…… g.DrawString(str, font, new SolidBrush(Color.Red), stringStart, stringFormat); //……

坐标计算

五、示例程序源代码下载

源工程文件:

https://files.cnblogs.com/files/lesliexin/StringFormat.7z

[C#] StringFormat详解之文本方向、对齐的更多相关文章

  1. 从硬件到语言,详解C++的内存对齐(memory alignment)

    转载请保留以下声明 作者:赵宗晟 出处:https://www.cnblogs.com/zhao-zongsheng/p/9099603.html 很多写C/C++的人都知道“内存对齐”的概念以及规则 ...

  2. 从硬件到语言,详解C++的内存对齐(memory alignment)(一)

    作者:赵宗晟 出处:https://www.cnblogs.com/zhao-zongsheng/p/9099603.html 很多写C/C++的人都知道“内存对齐”的概念以及规则,但不一定对他有很深 ...

  3. Markdown语法详解-cnblog

    博客的重要性 博客,英文名为Blog,它的正式名称为网络日记. 为什么要写博客? 需要总结和思考.有时候我们一直在赶路,却忘了放慢脚步 提升文笔组织能力 提升学习总结能力 提升逻辑思维能力 帮助他人, ...

  4. Android开发:文本控件详解——TextView(一)基本属性

    一.简单实例: 新建的Android项目初始自带的Hello World!其实就是一个TextView. 在activity_main.xml中可以新建TextView,从左侧组件里拖拽到右侧预览界面 ...

  5. 2.3.1 TextView(文本框)详解

    http://www.runoob.com/w3cnote/android-tutorial-textview.html 1.基础属性详解: 通过下面这个简单的界面,我们来了解几个最基本的属性: 布局 ...

  6. [转]C语言字节对齐问题详解

    C语言字节对齐问题详解 转载:https://www.cnblogs.com/clover-toeic/p/3853132.html 引言 考虑下面的结构体定义: typedef struct{ ch ...

  7. java使用POI操作XWPFDocument中的XWPFRun(文本)对象的属性详解

    java使用POI操作XWPFDocument中的XWPFRun(文本)对象的属性详解 我用的是office word 2016版 XWPFRun是XWPFDocument中的一段文本对象(就是一段文 ...

  8. Linux 文本对比 diff 命令详解(整理)

    diff 命令详解 1.概述 windows系统下面就有不错的文本对比工具可以使用,例如常用的Beyond Compare,WinMerge都是图形界面的比较工具而且使用非常方便,如果你仅仅是在win ...

  9. Android中Activity运行时屏幕方向与显示方式详解

    现在我们的手机一般都内置有方向感应器,手机屏幕会根据所处位置自动进行横竖屏切换(前提是未锁定屏幕方向).但有时我们的应用程序仅限在横屏或者竖屏状态下才可以运行,此时我们需要锁定该程序Activity运 ...

随机推荐

  1. 教你如何入手用python实现简单爬虫微信公众号并下载视频

    主要功能 如何简单爬虫微信公众号 获取信息:标题.摘要.封面.文章地址 自动批量下载公众号内的视频 一.获取公众号信息:标题.摘要.封面.文章URL 操作步骤: 1.先自己申请一个公众号 2.登录自己 ...

  2. python之elasticsearch查询

    下载所需模块 python安装好的情况下,通过pip install elasticsearch进行es模块的安装 安装完成后通过pip list命中查询 导入模块 from elasticsearc ...

  3. 解决IE升级后必须以管理员运行的问题

    很多网友可能都遇到过这样的问题,在ie升级后,无法打开,必须以管理员身份运行.今天我也遇到了这个问题.最终找到了解决办法. 1.Win + R 2.输入 regedit,定位到 HKEY_CURREN ...

  4. 从源码解读Spring如何解决bean循环依赖

    1 什么是bean的循环依赖 循环依赖的原文是circular reference,指多个对象相互引用,形成一个闭环. 以两个对象的循环依赖为例: Spring中的循环依赖有 3 种情况: 构造器(c ...

  5. Python初学者常见错误问题汇总

    1.在客户端和服务端如何传递数组? 答:在客户端和服务端可以使用json进行数据传输.在客户端把数据转换成json字符串,然后使用POST方法发送给服务端. 服务端收集到数据之后,使用json.loa ...

  6. 文件读取的时候要留意 -- 序列化serialize()与反序列化unserialize():

    原文:https://blog.csdn.net/little_rabbit_baby/article/details/53840543 序列化serialize()与反序列化unserialize( ...

  7. 3.k均值的算法

    一.课堂练习 # 课堂练习 from sklearn.datasets import load_iris # 导入鸢尾花数据 iris=load_iris() iris iris.keys() dat ...

  8. 【三剑客】awk函数

    1. 内置函数 awk的内置函数有算术.字符串.时间.位操作和其它杂项的函数. 1.1 算术函数 atan2(y,x)  返回弧度的反正切(y/x) cos(expr)  返回expr的余弦(以弧度形 ...

  9. 标准库ConfigParser模块

    用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser. 来看一个好多软件的常见文档格式如下: 1 2 3 4 5 6 7 8 9 10 11 12 ...

  10. 【React踩坑记五】React项目中引入并使用react-ace代码编辑插件(自定义列表提示)

    最近有一个引入sql编辑器插件的需求,要求代码高亮显示,代码智能提示,以及支持自定义代码提示列表等功能.中途在自定义代码提示列表中由于没有相关demo,所以踩了一些坑,遂将其整理如下,以便日后查看. ...