【问题标题】:GraphicsPath eliminate text borderGraphicsPath 消除文字边框
【发布时间】:2014-03-13 10:27:22
【问题描述】:

我正在使用GraphicsPath 对象在矩形中绘制文本。矩形比文本大,我想在矩形的任何角以及边缘的中心绘制文本。

我遇到的问题是,当我绘制路径时,源矩形周围会留下一个边框。我希望能够消除该边框并使文本接触其边界矩形。

这是我的代码:

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);
}

结果如下:

基本上,我希望红色矩形(及其包含的文本)接触蓝色矩形,并消除它们之间的边框。另外,我需要使用GraphicsPath 而不是DrawString

【问题讨论】:

  • 尝试使用sf = new StringFormat(StringFormat.GenericTypographic)去除左右边距。我不知道顶部和底部边距。我认为不同的问题。
  • 你自找麻烦。字形悬垂,以及下降和变音符号的垂直空间是棘手的排版细节。你得到了 GraphicsPath.Bounds,使用 Graphics.TranslateTransform() 将它移动到你想要的位置。
  • @HansPassant 现在我知道空间是留给后代和变音符号的。如果您输入答案,我很乐意接受。

标签: c# winforms drawing gdi+


【解决方案1】:

我最终编写了一个辅助方法来计算矩形的偏移量并在绘制之前翻译文本。这是我写的方法:

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);
}

我在Form1_Paint 方法中这样使用它:

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);
}

结果如下:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-07
    • 2019-04-10
    • 2014-08-02
    • 2015-05-11
    • 1970-01-01
    • 2016-03-03
    相关资源
    最近更新 更多