ярлык winform с эффектом гало или свечения на тексте - PullRequest
0 голосов
/ 06 апреля 2020

Следующий метод является частью унаследованного класса winform label. Цель состоит в том, чтобы создать эффект ореола или свечения на тексте. Пока что эффект на самом деле является контуром. Его стоит держать как его не плохо, но его еще нет.

protected override void OnPaint(PaintEventArgs e)
{
  if (this.Text.Length == 0) return;

  e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
  e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
  Rectangle rc = new Rectangle(ClientRectangle.X + Padding.Left,
                                ClientRectangle.Y + Padding.Top,
                                ClientRectangle.Width - (Padding.Left + Padding.Right),
                                ClientRectangle.Height - (Padding.Top + Padding.Bottom));
  StringFormat fmt = new StringFormat(StringFormat.GenericTypographic)
  {
    Alignment = TextAlign == ContentAlignment.TopLeft || TextAlign == ContentAlignment.MiddleLeft || TextAlign == ContentAlignment.BottomLeft
    ? StringAlignment.Near
    : TextAlign == ContentAlignment.TopCenter || TextAlign == ContentAlignment.MiddleCenter || TextAlign == ContentAlignment.BottomCenter
    ? StringAlignment.Center
    : StringAlignment.Far
  };

  if ((haloSize < 1) | (haloColor == Color.Transparent))
  {
    using (var brush = new SolidBrush(this.ForeColor))
    {
      e.Graphics.DrawString(Text, Font, brush, rc, fmt);
    }
  }
  else
  {
    using (var path = new GraphicsPath())
    using (var halopen = new Pen(new SolidBrush(this.haloColor), haloSize) { LineJoin = LineJoin.Round })
    using (var brush = new SolidBrush(ForeColor))
    {
      if (fmt.Alignment == StringAlignment.Center) rc.X += rc.Width / 2;
      if (fmt.Alignment == StringAlignment.Far) rc.X += rc.Width;
      path.AddString(Text, Font.FontFamily, (int)Font.Style, rc.Height, rc.Location, fmt);
      //path.AddString(Text, Font.FontFamily, (int)Font.Style, rc.Height, rc, fmt);
      e.Graphics.DrawPath(halopen, path);
      e.Graphics.FillPath(brush, path);
    }
  }
}

Два вопроса.

  1. Почему строка, закомментированная с использованием AddString с Rectangle, не работает, но работает с Point?
  2. Эффект свечения гало может быть достигнут с постепенным уменьшением размера и цвета bru sh, но все равно, что изобретать новое колесо. Есть ли простой способ сделать это или библиотека с открытым исходным кодом уже с этим?

1 Ответ

0 голосов
/ 06 апреля 2020
  1. Исходная строка надписей была слишком большой для коробки. Я думаю, что он отменил отрисовку, потому что это было отсечение.
  2. Многопроходный режим работает и создает градиент, но он может быть недостаточно быстрым, чтобы добавить эффект мерцания в свечение.

Эффект свечения / ореола обеспечивает хорошую контрастность для фонового изображения, которое соответствует основному цвету текста. В основном это цель, но она ничего не делает для текста, который слишком длинен для метки. Я мог бы добавить это позже.

    protected override void OnPaint(PaintEventArgs e)
    {
      if (this.Text.Length == 0) return;

      e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
      e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
      e.Graphics.CompositingMode = CompositingMode.SourceOver;
      Rectangle rc = new Rectangle(ClientRectangle.X + Padding.Left,
                                    ClientRectangle.Y + Padding.Top,
                                    ClientRectangle.Width - (Padding.Left + Padding.Right),
                                    ClientRectangle.Height - (Padding.Top + Padding.Bottom));
      StringFormat fmt = new StringFormat(StringFormat.GenericTypographic)
      {
        Alignment = TextAlign == ContentAlignment.TopLeft || TextAlign == ContentAlignment.MiddleLeft || TextAlign == ContentAlignment.BottomLeft
        ? StringAlignment.Near
        : TextAlign == ContentAlignment.TopCenter || TextAlign == ContentAlignment.MiddleCenter || TextAlign == ContentAlignment.BottomCenter
        ? StringAlignment.Center
        : StringAlignment.Far
      };
      float EmSize = rc.Height * 0.70f //Font.SizeInPoints  disreguard fontsize and fit height of label
                     * (Font.FontFamily.GetCellAscent(Font.Style) + Font.FontFamily.GetCellDescent(Font.Style))
                     / Font.FontFamily.GetEmHeight(Font.Style);
      using (var path = new GraphicsPath())
      using (var brush = new SolidBrush(ForeColor))
      {
        path.AddString(Text, Font.FontFamily, (int)Font.Style, EmSize, rc, fmt);
        if ((haloSize > 0) & (haloColor != Color.Transparent))
        {
          using (var halopen = new Pen(new SolidBrush(Color.FromArgb(255 / (int)haloSize, haloColor)), haloSize) { LineJoin = LineJoin.Round })
          {
            for (int i = (int)haloSize; i > 0; --i)
            {
              halopen.Width = i;
              e.Graphics.DrawPath(halopen, path);
            }
          }
        }
        e.Graphics.FillPath(brush, path);
      }
    }
...