如何certificate标签中的文字

我有一个标签显示在一行以上,我想certificate其中的文字(左右对齐)。 实现这一目标的最佳方法是什么?

这是TaW提出的解决方案的实现。 它只是实现的基本代码 – 没有自动重新调整等。

 public void Justify(System.Windows.Forms.Label label) { string text = label.Text; string[] lines = text.Split(new[]{"\r\n"}, StringSplitOptions.None).Select(l => l.Trim()).ToArray(); List result = new List(); foreach (string line in lines) { result.Add(StretchToWidth(line, label)); } label.Text = string.Join("\r\n", result); } private string StretchToWidth(string text, Label label) { if (text.Length < 2) return text; // A hair space is the smallest possible non-visible character we can insert const char hairspace = '\u200A'; // If we measure just the width of the space we might get too much because of added paddings so we have to do it a bit differently double basewidth = TextRenderer.MeasureText(text, label.Font).Width; double doublewidth = TextRenderer.MeasureText(text + text, label.Font).Width; double doublewidthplusspace = TextRenderer.MeasureText(text + hairspace + text, label.Font).Width; double spacewidth = doublewidthplusspace - doublewidth; //The space we have to fill up with spaces is whatever is left double leftoverspace = label.Width - basewidth; //Calculate the amount of spaces we need to insert int approximateInserts = Math.Max(0, (int)Math.Floor(leftoverspace / spacewidth)); //Insert spaces return InsertFillerChar(hairspace, text, approximateInserts); } private static string InsertFillerChar(char filler, string text, int inserts) { string result = ""; int inserted = 0; for (int i = 0; i < text.Length; i++) { //Add one character of the original text result += text[i]; //Only add spaces between characters, not at the end if (i >= text.Length - 1) continue; //Determine how many characters should have been inserted so far int shouldbeinserted = (int)(inserts * (i+1) / (text.Length - 1.0)); int insertnow = shouldbeinserted - inserted; for (int j = 0; j < insertnow; j++) result += filler; inserted += insertnow; } return result; } 

在行动:
演示

不幸的是,只支持三种最基本和最简单的对齐方式: RightLeft和中。

第四个, JustifiedBlock ,在任何.NET控件中都不受支持,甚至在RichtTextBox也不支持:-(

唯一的解决方法是在单词之间添加空格或更好的较小的空白字符,如thin space (U + 2009)或hair space (U + 200A),即在常规空格之后,直到LabelHeight变化。 然后退一步,尝试找到下一个插入点,即下一行,依此类推……直到到达文本末尾。

有点棘手,但不是很难。

另一个实现。
这个只在单词之间插入“发空间”。

编辑:
添加了一个实现段落对齐的方法。
JustifyParagraph()JustifyLine()调用worker方法Justify()

EDIT2:
方法调用已更改。

 label1.Text = JustifyParagraph(label1.Text, label1.Font, label1.ClientSize.Width); public string JustifyParagraph(string text, Font font, int ControlWidth) { string result = string.Empty; List ParagraphsList = new List(); ParagraphsList.AddRange(text.Split(new[] { "\r\n" }, StringSplitOptions.None).ToList()); foreach (string Paragraph in ParagraphsList) { string line = string.Empty; int ParagraphWidth = TextRenderer.MeasureText(Paragraph, font).Width; if (ParagraphWidth > ControlWidth) { //Get all paragraph words, add a normal space and calculate when their sum exceeds the constraints string[] Words = Paragraph.Split(' '); line = Words[0] + (char)32; for (int x = 1; x < Words.Length; x++) { string tmpLine = line + (Words[x] + (char)32); if (TextRenderer.MeasureText(tmpLine, font).Width > ControlWidth) { //Max lenght reached. Justify the line and step back result += Justify(line.TrimEnd(), font, ControlWidth) + "\r\n"; line = string.Empty; --x; } else { //Some capacity still left line += (Words[x] + (char)32); } } //Adds the remainder if any if (line.Length > 0) result += line + "\r\n"; } else { result += Paragraph + "\r\n"; } } return result.TrimEnd(new[]{ '\r', '\n' }); } 

在此处输入图像描述
在此处输入图像描述

JustifyLines()仅处理单行文本(短于客户区)

 textBox1.Text = JustifyLines(textBox1.Text, textBox1.Font, textBox1.ClientSize.Width); public string JustifyLines(string text, Font font, int ControlWidth) { string result = string.Empty; List Paragraphs = new List(); Paragraphs.AddRange(text.Split(new[] { "\r\n" }, StringSplitOptions.None).ToList()); //Justify each paragraph and re-insert a linefeed foreach (string Paragraph in Paragraphs) { result += Justify(Paragraph, font, ControlWidth) + "\r\n"; } return result.TrimEnd(new[] {'\r', '\n'}); } 

在此处输入图像描述
在此处输入图像描述

工人方法

 private string Justify(string text, Font font, int width) { char SpaceChar = (char)0x200A; List WordsList = text.Split((char)32).ToList(); if (WordsList.Capacity < 2) return text; int NumberOfWords = WordsList.Capacity - 1; int WordsWidth = TextRenderer.MeasureText(text.Replace(" ", ""), font).Width; int SpaceCharWidth = TextRenderer.MeasureText(WordsList[0] + SpaceChar, font).Width - TextRenderer.MeasureText(WordsList[0], font).Width; //Calculate the average spacing between each word minus the last one int AverageSpace = ((width - WordsWidth) / NumberOfWords) / SpaceCharWidth; float AdjustSpace = (width - (WordsWidth + (AverageSpace * NumberOfWords * SpaceCharWidth))); //Add spaces to all words return ((Func)(() => { string Spaces = ""; string AdjustedWords = ""; for (int h = 0; h < AverageSpace; h++) Spaces += SpaceChar; foreach (string Word in WordsList) { AdjustedWords += Word + Spaces; //Adjust the spacing if there's a reminder if (AdjustSpace > 0) { AdjustedWords += SpaceChar; AdjustSpace -= SpaceCharWidth; } } return AdjustedWords.TrimEnd(); }))(); } 

关于RichTextBox。
@TaW表示它不支持Block Align,但这并不完全正确。
众所周知,RichTextBox基于RichEdit类,该类支持“Justification”。
这在旧的Platform SDK(带有示例)中报告。
RichTextBox在创建句柄期间显式截断了AdvancedTypographicsOption。
(这不是关于实现PARAFORMAT与PARAFORMAT2结构,这是无关紧要的,它是故意的)。

所以这对于糟糕的RichTextBox来说是一种“治愈”。 一个派生自它的类,并重写OnHandleCreated以重新启用“Justification”。
适用于段落级别或从之后开始。

 public class JustifiedRichTextBox : RichTextBox { [DllImport("user32", CharSet = CharSet.Auto)] private static extern int SendMessage(IntPtr hWnd, int msg, int wParam, [In] [Out] ref PARAFORMAT2 pf); [DllImport("user32", CharSet = CharSet.Auto)] private static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam); public enum TextAlignment { Left = 1, Right, Center, Justify } private const int EM_SETEVENTMASK = 1073; private const int EM_GETPARAFORMAT = 1085; private const int EM_SETPARAFORMAT = 1095; private const int EM_SETTYPOGRAPHYOPTIONS = 1226; private const int TO_ADVANCEDTYPOGRAPHY = 0x1; private const int WM_SETREDRAW = 11; private const int PFM_ALIGNMENT = 8; private const int SCF_SELECTION = 1; [StructLayout(LayoutKind.Sequential)] private struct PARAFORMAT2 { //---------------------------------------- public int cbSize; // PARAFORMAT 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; // PARAFORMAT2 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; } private int updating = 0; private int oldEventMask = 0; public new TextAlignment SelectionAlignment {//SelectionAlignment is not overridable get { PARAFORMAT2 pf = new PARAFORMAT2(); pf.cbSize = Marshal.SizeOf(pf); SendMessage(this.Handle, EM_GETPARAFORMAT, SCF_SELECTION, ref pf); if ((pf.dwMask & PFM_ALIGNMENT) == 0) return TextAlignment.Left; return (TextAlignment)pf.wAlignment; } set { PARAFORMAT2 pf = new PARAFORMAT2(); pf.cbSize = Marshal.SizeOf(pf); pf.dwMask = PFM_ALIGNMENT; pf.wAlignment = (short)value; SendMessage(this.Handle, EM_SETPARAFORMAT, SCF_SELECTION, ref pf); } } //Overrides OnHandleCreated to enable RTB advances options protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); //EM_SETTYPOGRAPHYOPTIONS allows to enable RTB (RichEdit) Advanced Typography SendMessage(this.Handle, EM_SETTYPOGRAPHYOPTIONS, TO_ADVANCEDTYPOGRAPHY, TO_ADVANCEDTYPOGRAPHY); } } //JustifiedRichTextBox 

在此处输入图像描述
在此处输入图像描述