-2

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

在此处输入图像描述

除了每个字符集位置

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 没有分布对齐。所以我想知道一种如何在矩形中分配字符串的方法。

4

3 回答 3

1

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

完全对齐

    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);
        }
    }
于 2013-05-22T15:00:59.013 回答
1

For the moment, I'm going to assume you can/will use the Win32 API (e.g., via. P/Invoke). .NET may have a wrapper for the function I'm going to suggest (but then again, it may not -- I'm really not sure). If it does, it'll be up to you to find and use it. Most of what I'm suggesting is more about the basic approach than the function anyway.

You can use GetTextExtentExPointI, which will compute the size of a rectangle necessary to hold a set characters you specify and (importantly) the horizontal position of each character in that rectangle.

So, what you want to do is use this to compute the size of a rectangle and position of each character in that rectangle, with it assuming normal kerning of the characters. Then, you'll divide the width of that rectangle into the width you actually want. This will give you a factor by which each position must increase to get that character to the position you want. You'll then multiply the position it returned for each character by that factor to get your desired position.

Just for example, let's assume it gave you positions of 0, 17, 35 and 44 for the characters with normal spacing. Let's also assume your target rectangle is 1.8 times as wide as the rectangle it computed for normal spacing. You'll take each of those positions and multiply by 1.8 to get the position you want to use for that character, giving 0, 31, 63, and 79 for the "corrected" positions.

Then you'll (obviously enough) go through your string and draw each character at the computed position.

于 2013-05-22T03:09:24.843 回答
0

这是我使用 .Net 托管方法对@Jerry Coffin 算法的尝试: 完全对齐的文本

    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);
        }
    }
于 2013-05-22T13:07:41.227 回答