質問

I'm using the GraphicsPath object to draw text in a rectangle. The rectangle is larger than the text, and I want to draw the text in any of the rectangle's corners, and also at the center of its edges.

The problem I have is that when I draw the path, a border is being left around the source rectangle. I want to be able to eliminate that border and make the text touch its bounding rectangle.

Here is the code I have:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    var g = e.Graphics;
    g.SmoothingMode = SmoothingMode.HighQuality;

    Rectangle textRect = new Rectangle(100, 100, 150, 150);
    Font f = new Font("Arial", 16);
    float emSize = f.Height * f.FontFamily.GetCellAscent(f.Style) /
               f.FontFamily.GetEmHeight(f.Style);

    foreach (StringAlignment lineAlignment in Enum.GetValues(typeof(StringAlignment)))
    {
        foreach (StringAlignment alignment in Enum.GetValues(typeof(StringAlignment)))
        {
            StringFormat sf = new StringFormat() { LineAlignment = lineAlignment, Alignment = alignment };
            using (GraphicsPath gp = new GraphicsPath())
            {
                gp.AddString("txt", f.FontFamily, (int)f.Style, emSize, textRect, sf);
                RectangleF bounds = gp.GetBounds();
                g.FillPath(Brushes.Black, gp);
                g.DrawRectangle(Pens.Red, Rectangle.Round(bounds));
            }
        }
    }          

    g.DrawRectangle(Pens.Blue, textRect);
}

And here is the result:

Result

Basically, I want the red rectangles (and the text they contain) to touch the blue rectangle, and to eliminate the border between them. Also, I need to use the GraphicsPath and not DrawString.

役に立ちましたか?

解決

I ended up writing a helper method to calculate the offset of the rectangles and translate the text before drawing it. Here is the method I wrote:

private PointF FixAlignment(RectangleF parentRect, RectangleF childRect,
    StringAlignment lineAlignment, StringAlignment alignment)
{
    float xOffset = 0;
    float yOffset = 0;

    switch (lineAlignment)
    {
        case StringAlignment.Near:
            yOffset = parentRect.Top - childRect.Top;
            break;
        case StringAlignment.Far:
            yOffset = parentRect.Bottom - childRect.Bottom;
            break;
    }

    switch (alignment)
    {
        case StringAlignment.Near:
            xOffset = parentRect.Left - childRect.Left;
            break;
        case StringAlignment.Far:
            xOffset = parentRect.Right - childRect.Right;
            break;
    }

    return new PointF(xOffset, yOffset);
}

I used it in the Form1_Paint method like this:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    var g = e.Graphics;
    g.SmoothingMode = SmoothingMode.HighQuality;

    Rectangle textRect = new Rectangle(100, 100, 150, 150);
    Font f = new Font("Arial", 16);
    float emSize = f.Height * f.FontFamily.GetCellAscent(f.Style) /
               f.FontFamily.GetEmHeight(f.Style);

    foreach (StringAlignment lineAlignment in Enum.GetValues(typeof(StringAlignment)))
    {
        foreach (StringAlignment alignment in Enum.GetValues(typeof(StringAlignment)))
        {
            StringFormat sf = new StringFormat() { LineAlignment = lineAlignment, Alignment = alignment };
            using (GraphicsPath gp = new GraphicsPath())
            {
                gp.AddString("txt", f.FontFamily, (int)f.Style, emSize, textRect, sf);
                RectangleF bounds = gp.GetBounds();

                // Calculate the rectangle offset
                PointF offset = FixAlignment(textRect, bounds, lineAlignment, alignment);
                // Translate using the offset
                g.TranslateTransform(offset.X, offset.Y);
                g.FillPath(Brushes.Black, gp);
                g.DrawRectangle(Pens.Red, Rectangle.Round(bounds));

                // Translate back to the original location
                g.TranslateTransform(-offset.X, -offset.Y);
            }
        }
    }

    g.DrawRectangle(Pens.Blue, textRect);
}

Here is the result:

Result

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top