绘制多行文字时会用到DrawText函数或Graphics.DrawString方法,但它们都无法设置行距,也无法设置段落间距。下图是用DrawString方法绘制的两段文字,可以看到中文测试段落的行距非常小。

我们可以利用RTF格式来设置行距和段落间距,下图是测试结果:

C#源代码:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;namespace WindowsFormsApplication1
{public partial class Form1 : Form{private struct RECT{public int Left;public int Top;public int Right;public int Bottom;}private struct CHARRANGE{public int cpMin;public int cpMax;}private struct FORMATRANGE{public IntPtr hDC;public IntPtr hDCTarget;public RECT rc;public RECT rcPage;public CHARRANGE chrg;}private struct PARAFORMAT2{public int cbSize;public uint dwMask;public short wNumbering;public short wReserved;public int dxStartIndent;public int dxRightIndent;public int dxOffset;public short wAlignment;public short cTabCount;[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]public int[] rgxTabs;public int dySpaceBefore;public int dySpaceAfter;public int dyLineSpacing;public short sStyle;public byte bLineSpacingRule;public byte bOutlineLevel;public short wShadingWeight;public short wShadingStyle;public short wNumberingStart;public short wNumberingStyle;public short wNumberingTab;public short wBorderSpace;public short wBorderWidth;public short wBorders;}[DllImport("user32", CharSet = CharSet.Auto)]private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, ref PARAFORMAT2 lParam);[DllImport("user32", CharSet = CharSet.Auto)]private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, ref FORMATRANGE lParam);public const int WM_USER = 0x0400;public const int EM_FORMATRANGE = WM_USER + 57;public const int EM_SETPARAFORMAT = WM_USER + 71;public const int PFM_LINESPACING = 0x00000100;public const int PFM_SPACEBEFORE = 0x00000040;public const int PFM_SPACEAFTER = 0x00000080;public Form1(){InitializeComponent();this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);}private void Form1_Load(object sender, EventArgs e){this.Size = new Size(400, 200);}private void Form1_Paint(object sender, PaintEventArgs e){RichTextBox richTextBox = new RichTextBox();richTextBox.Text = "第一段是中文字符测试内容,第二段是英文字符测试内容,中文的行距明显更小。\r\nYou have to believe in yourself. That's the secret of success. - Charles Chaplin";richTextBox.SelectAll();richTextBox.Font = this.Font;richTextBox.BackColor = this.BackColor;int intTwipsPerPixel = (int)(1440 / e.Graphics.DpiX);PARAFORMAT2 paraFormat = new PARAFORMAT2();paraFormat.cbSize = Marshal.SizeOf(paraFormat);paraFormat.bLineSpacingRule = 3;paraFormat.dyLineSpacing = 20 * intTwipsPerPixel;  //行距paraFormat.dySpaceAfter = 10 * intTwipsPerPixel; //段落后的间距paraFormat.dwMask = PFM_LINESPACING | PFM_SPACEAFTER;richTextBox.SelectAll();SendMessage(richTextBox.Handle, EM_SETPARAFORMAT, 0, ref paraFormat);IntPtr hDC = e.Graphics.GetHdc();FORMATRANGE formatRange = new FORMATRANGE();formatRange.chrg.cpMin = 0;formatRange.chrg.cpMax = richTextBox.Text.Length;formatRange.rc.Left = 20 * intTwipsPerPixel;formatRange.rc.Right = (this.ClientSize.Width-20) * intTwipsPerPixel;formatRange.rc.Top = 20 * intTwipsPerPixel;formatRange.rc.Bottom = (this.ClientSize.Height-20) * intTwipsPerPixel;formatRange.rcPage = formatRange.rc;formatRange.hDC = hDC;formatRange.hDCTarget = hDC;SendMessage(richTextBox.Handle, EM_FORMATRANGE, 1, ref formatRange);e.Graphics.ReleaseHdc(hDC);richTextBox.Dispose();}}
}

VB.Net源代码:

Imports System.Runtime.InteropServicesPublic Class Form1Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As FORMATRANGE) As IntegerPrivate Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByRef lParam As PARAFORMAT2) As IntegerPrivate Structure RECTDim Left As IntegerDim Top As IntegerDim Right As IntegerDim Bottom As IntegerEnd StructurePrivate Structure CHARRANGEDim cpMin As IntegerDim cpMax As IntegerEnd StructurePrivate Structure FORMATRANGEDim hDC As IntPtrDim hdcTarget As IntPtrDim rc As RECTDim rcPage As RECTDim chrg As CHARRANGEEnd StructurePrivate Structure PARAFORMAT2Dim cbSize As IntegerDim dwMask As UInt32Dim wNumbering As ShortDim wReserved As ShortDim dxStartIndent As IntegerDim dxRightIndent As IntegerDim dxOffset As IntegerDim wAlignment As ShortDim cTabCount As Short<MarshalAs(UnmanagedType.ByValArray, SizeConst:=32)> _Dim rgxTabs As Integer()Dim dySpaceBefore As IntegerDim dySpaceAfter As IntegerDim dyLineSpacing As IntegerDim sStyle As ShortDim bLineSpacingRule As ByteDim bOutlineLevel As ByteDim wShadingWeight As ShortDim wShadingStyle As ShortDim wNumberingStart As ShortDim wNumberingStyle As ShortDim wNumberingTab As ShortDim wBorderSpace As ShortDim wBorderWidth As ShortDim wBorders As ShortEnd StructurePrivate Const WM_USER As Integer = &H400Private Const EM_FORMATRANGE As Integer = WM_USER + 57Private Const EM_SETPARAFORMAT As Integer = WM_USER + 71Private Const PFM_LINESPACING As Integer = &H100Private Const PFM_SPACEBEFORE As Integer = &H40Private Const PFM_SPACEAFTER As Integer = &H80Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.LoadMe.Size = New Size(400, 200)End SubPrivate Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.PaintDim richTextBox As New Windows.Forms.RichTextBoxrichTextBox.Text = "第一段是中文字符测试内容,第二段是英文字符测试内容,中文的行距明显更小。" & vbCrLf & "You have to believe in yourself. That's the secret of success. - Charles Chaplin"richTextBox.SelectAll()richTextBox.Font = Me.FontrichTextBox.BackColor = Me.BackColorDim intTwipsPerPixel = 1440 / e.Graphics.DpiXDim paraFormat As New PARAFORMAT2paraFormat.cbSize = Marshal.SizeOf(paraFormat)paraFormat.bLineSpacingRule = 3paraFormat.dyLineSpacing = 20 * intTwipsPerPixel '行距paraFormat.dySpaceAfter = 10 * intTwipsPerPixel '段落后的间距paraFormat.dwMask = PFM_LINESPACING Or PFM_SPACEAFTERrichTextBox.SelectAll()SendMessage(richTextBox.Handle, EM_SETPARAFORMAT, 0, paraFormat)Dim hDC As IntPtr = e.Graphics.GetHdc()Dim formatRange As FORMATRANGEformatRange.chrg.cpMin = 0formatRange.chrg.cpMax = Len(richTextBox.Text)formatRange.rc.Left = 20 * intTwipsPerPixelformatRange.rc.Right = (Me.ClientSize.Width - 20) * intTwipsPerPixelformatRange.rc.Top = 20 * intTwipsPerPixelformatRange.rc.Bottom = (Me.ClientSize.Height - 20) * intTwipsPerPixelformatRange.rcPage = formatRange.rcformatRange.hDC = hDCformatRange.hdcTarget = hDCSendMessage(richTextBox.Handle, EM_FORMATRANGE, 1, formatRange)e.Graphics.ReleaseHdc(hDC)richTextBox.Dispose()End SubEnd Class

程序中用到的bLineSpacingRule,其取值可以参考:
https://learn.microsoft.com/en-us/windows/win32/api/richedit/ns-richedit-paraformat2

bLineSpacingRule = 0:单倍行距
bLineSpacingRule = 1:1.5倍行距
bLineSpacingRule = 2:2倍行距
bLineSpacingRule = 3:固定行距,用dyLineSpacing指定行距

用RTF格式解决DrawText函数或Graphics.DrawString方法不能设置行距的问题相关推荐

  1. [转] C# 绘制报表,使用Graphics.DrawString 方法

    原文 Graphics.DrawString 方法 在指定位置并且用指定的 Brush 和Font 对象绘制指定的文本字符串. public void DrawString(string s,Font ...

  2. VC++设置字体 字幕变色功能的实现 DrawText函数 本章小结

    目录 设置字体 字幕变色功能的实现 DrawText函数 本章小结 接上:VC++字符输入 ASCII码 接下: 设置字体 MFC提供了一个CFont类专门用来设置字体.这个类派生于CGdiObjec ...

  3. c语言滚动字幕的原理编程,c#中通过Graphics.DrawString实现滚动字幕的原理和代码实例...

    c#中通过Graphics.DrawString实现滚动字幕的原理和代码实例 在c#中其实滚动屏幕的实现很简单,只需要用到Graphics.DrawString方法. Graphics.DrawStr ...

  4. drawtext函数用法设置字体 qt,解决QPainter::drawText修改文字方向

    今天在绘制双坐标曲线的时候需要修改y轴文字提示 QPainter的drawText()函数提供了绘制文本的功能. 它有几种重载形式,我们使用了其中的一种,即制定文本的坐标然后绘制 正常我们的文字书写方 ...

  5. DrawText函数

    DrawText函数功能:该函数在指定的矩形里写入格式化文本,根据指定的方法对文本格式化(扩展的制表符,字符对齐.折行等). 中文名DrawText函数所属学科计算机函数原型intDrawText(H ...

  6. [vb]格式输出Format函数

    格式输出Format函数 Format函数用于制定字符串或数字的输出格式. 语法:x = Format (expression, fmt ) expression是所输出的内容.fmt是指输出的格式, ...

  7. c++语言drawtext字体旋转,使用DrawText函数对文本进行换行处理的实现

    DrawText函数原型: int DrawText( HDC hDC, // handle to DC LPCTSTR lpString, // text to draw int nCount, / ...

  8. Outlook使用RTF格式发信出现Winmail.dat附件事宜

    接到用户反馈对方使用Outlook客户端发信过来,我们收到的呈现是winmail.dat附件,我们单独还要找第三方工具软件解析出来. 原理:Outlook选用的格式为微软自研RTF格式(常规是HTML ...

  9. outlook 发送 html,在Outlook中发送给Internet收件人时,如何将RTF格式更改为HTML?

    在Outlook中发送给Internet收件人时,如何将RTF格式更改为HTML? 如果您在Outlook中撰写并以RTF格式发送电子邮件,许多Internet收件人将无法正常在网页上查看此电子邮件. ...

最新文章

  1. Kotlin 一个好用的新功能:Parcelize
  2. 大型网站系统架构演化之路
  3. linux中的ftp是什么意思,什么是linux的ftp
  4. SQL View 的使用语法与原则
  5. 项目管理软件伙伴https://www.huobanyun.cn/
  6. 游戏开发中的数学和物理算法(18):缩放
  7. 华硕主板放电才能点亮
  8. 十大热门编程语言的介绍
  9. 图书管理系统/库存管理系统等计算机毕业论文设计
  10. android tcp 工具,TcpIp工具包app
  11. 深入探讨Android异步精髓Handler
  12. sqlParameter的使用------七个构造函数
  13. 路在脚下,何去何从?
  14. 计算机NIC配置,在主计算机或 VM 上创建新的 NIC 团队
  15. Robot Framework installation not found. To run tests, you need to install Robot Framework separately
  16. matlab 相位校正,科学网—全相位比值校正法 - 王兆华的博文
  17. Sequencer框架
  18. We‘re sorry but XXX doesn‘t work properly without JavaScript enabled.
  19. java mp4 合并_使用 Python 把多个 MP4 合成一个视频
  20. 布袋除尘器过滤风速多少_太原布袋式除尘器过滤风速一般多大

热门文章

  1. 当Python和R遇上北京二手房(下)
  2. 「转」史上最详细 快递公司各种投诉内幕
  3. 实用的 PyCharm 教程
  4. 【项目实战】YOLOV5 +实时吸烟目标检测+手把手教学+开源全部
  5. ssh备考-07 搭建spring框架环境
  6. Soc-e在FPGA上为任务关键型应用量身定制的IEEE 1588感知以太网交换机
  7. 计算机CCT考试模拟操作题,基础计算机cct模拟测试模拟题.doc
  8. win 2008 创建密码重置盘
  9. 干货分享,使用python爬虫构建免费代理IP池
  10. 解决Connection closed by remote host