在使用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. T - Nash Matrix CodeForces - 1316D

    题意: 输入n行数,没行由2*n个数,表示一个坐标(x,y). 如果x和y==-1表示从该点(i,j)出发,按照构造的前移动不会停下. 否则就要到点(x,y)处停下. 题解: 首先处理-1  枚举每个 ...

  2. XML-解析失败原因初步分析

    更多精彩文章请关注公众号『大海的BLOG』 首先放出有问题的代码 之所以直入主题是因为肝完了事情,急需入睡.hiahia hiboard:updateUrl="https://xxx.com ...

  3. vue2.x学习笔记(十三)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12595860.html. 组件的注册 注册组件有一些规范约定与注意事项. 组件名的命名规范 在注册一个组件的时候, ...

  4. kioptrix靶机记录

    靶机地址:172.16.1.193 Kali地址:172.16.1.107 首页为Apache测试页,没看到有价值信息 尝试目录扫描: 点击查看: http://172.16.1.193/index. ...

  5. Springboot:员工管理之公共页面提取 高亮显示(十(5))

    把顶部和左侧的公共代码分别放到header.html和left.html中 顶部代码:resources\templates\header.html 主内容展示: <!DOCTYPE html& ...

  6. 前端面试的那些事儿(1)~JavaScript 原始数据类型

    前言 自我总结面试常问的一些细节,方便不断回顾与补充.第一次发表文章,如有问题或不足之处望及时指出. JavaScript 原始数据类型 1.1 基础数据类型 7大基础数据类型 boolean nul ...

  7. Java 虚拟机中的运行时数据区分析

    本文基于 JDK1.8 阐述分析 运行过程 我们都知道 Java 源文件通过编译器编译后,能产生相应的 .Class 文件,也就是字节码文件.而字节码文件通过 Java 虚拟机中的解释器,编译成特定机 ...

  8. thinkphp5.0 配置文件加载路径说明

    在thinphp5.0框架里,js,css等配置文件都是加载在/public/static的目录下,所以要引用这些文件,路径必须是要写好的,代码如图: return [ // 默认模块名 'defau ...

  9. oracle获取表字段及表注释的相关操作

    一.获取表字段: select * from user_tab_columns where Table_Name='用户表' user_tab_columns 为当前用户的columns,除此之外还有 ...

  10. Uva 1754 Posterize

    #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) #defi ...