我如何在矩形中分配字符串

时间:2013-05-22 02:43:23

标签: c# winforms

我想在矩形中分发字符串。

enter image description here

除了每个字符集位置

Rectangle  displayRectangle = new Rectangle (new Point(40, 40), new Size (80, 80));

StringFormat format1 = new StringFormat(StringFormatFlags.NoClip);

format1.LineAlignment = StringAlignment.Center; 

e.Graphics.DrawRectangle(Pens.Black, displayRectangle);

e.Graphics.DrawString("Showing Format1", this.Font,

Brushes.Black, (RectangleF)displayRectangle, format1);

但是,StringFormat Alignment没有分配对齐。所以我想知道如何在矩形中分配字符串。

3 个答案:

答案 0 :(得分:1)

目前,我将假设您可以/将使用Win32 API(例如,通过.P / Invoke)。 .NET可能有一个我将要建议的函数的包装器(但是,它可能不会 - 我真的不确定)。如果确实如此,您可以自行查找并使用它。我建议的大部分内容都是关于基本方法而不是函数。

您可以使用GetTextExtentExPointI,它将计算保存您指定的设定字符所需的矩形大小,并且(重要的是)计算该矩形中每个字符的水平位置。

所以,你想要做的就是用它来计算矩形的大小和那个矩形中每个字符的位置,假设字符是正常的字距。然后,您将该矩形的宽度划分为您实际想要的宽度。这将为您提供一个因子,每个位置必须增加以使该角色达到您想要的位置。然后,您将为每个字符返回的位置乘以该因子,以获得您想要的位置。

例如,让我们假设它为正常间距的字符提供了0,17,35和44的位置。我们还假设您的目标矩形是它为正常间距计算的矩形的1.8倍宽。您将获取每个位置并乘以1.8以获得您想要用于该角色的位置,为“已校正”位置提供0,31,63和79.

然后你(显然已经)通过你的字符串并在计算位置绘制每个字符。

答案 1 :(得分:1)

如果您只想在显示矩形的中间均匀分布字符,请执行以下操作:

Full Justify

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        string text = "this is distribute";

        Rectangle displayRectangle = new Rectangle(new Point(40, 40), new Size(400, 80));
        e.Graphics.DrawRectangle(Pens.Black, displayRectangle);

        int step = displayRectangle.Width / text.Length;
        SizeF szF = e.Graphics.MeasureString(text, this.Font); // just to get the HEIGHT

        int y = (displayRectangle.Y + displayRectangle.Height / 2) - (int)szF.Height / 2;
        for (int i = 0; i < text.Length; i++)
        {
            e.Graphics.DrawString(text.Substring(i, 1), this.Font, Brushes.Black, displayRectangle.X + (i * step), y);
        }
    }

答案 2 :(得分:0)

这是我使用.Net托管方法刺激@Jerry Coffin的算法: Full Justified Text

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        string text = "this is distribute";
        Rectangle displayRectangle = new Rectangle(new Point(40, 40), new Size(400, 80));
        e.Graphics.DrawRectangle(Pens.Black, displayRectangle);

        StringFormat format1 = new StringFormat(StringFormatFlags.NoClip);
        format1.LineAlignment = StringAlignment.Center;
        format1.Alignment = StringAlignment.Near;

        // SetMeasurableCharacterRanges() can only handle 32 regions max at a time!
        // The below workaround simply measures each character separately:
        RectangleF rcF = (RectangleF)displayRectangle;
        List<Region> regions = new List<System.Drawing.Region>();
        for (int i = 0; i < text.Length; i++)
        {
            format1.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(i, 1)});    
            regions.AddRange(e.Graphics.MeasureCharacterRanges(text, this.Font, rcF, format1));
        }

        RectangleF minBounds = regions[0].GetBounds(e.Graphics);
        RectangleF maxBounds = regions[regions.Count - 1].GetBounds(e.Graphics);
        float ratio = (float)displayRectangle.Width / (float)((maxBounds.X + maxBounds.Width) - minBounds.X);

        for(int i = 0; i < regions.Count; i++)
        {
            Region region = regions[i];
            RectangleF boundsF = region.GetBounds(e.Graphics);
            PointF ptF = new PointF(displayRectangle.X + (int)((boundsF.Left - minBounds.X) * ratio), (int)boundsF.Top);
            e.Graphics.DrawString(text.Substring(i, 1), this.Font, Brushes.Black, ptF);
        }
    }