2014-03-13 51 views
1

我正在使用GraphicsPath對象在矩形中繪製文本。該矩形比文本大,我想在矩形的任何角落繪製文本,並且在其邊緣的中心繪製文本。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); 
} 

這裏是結果:

Result

基本上,我想要紅色的矩形(和它們所包含的文本)觸摸藍色矩形,並消除它們之間的邊界。另外,我需要使用GraphicsPath而不是DrawString

+0

嘗試使用'SF =新StringFormat(StringFormat.GenericTypographic)'擺脫左右邊距。我不知道上邊緣和底邊緣。不同的問題,我想。 – LarsTech

+0

你在問很多麻煩。字形懸垂,下行和垂直空間的垂直空間是棘手的版式細節。你得到了GraphicsPath.Bounds,使用Graphics.TranslateTransform()將它移動到你想要的位置。 –

+0

@HansPassant現在我明白,後代和變音符號的空間是存在的。如果你輸入一個答案,我會很樂意接受它。 – Ove

回答

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

下面是結果:

Result