我如何在油漆事件中绘制每一行不同颜色的字符串?

时间:2014-06-13 02:53:53

标签: c# .net winforms

此控件用于滚动文本。 我想用不同的颜色为文本的每一行着色。 文本写在textBox中,属性TextToScroll从textBox中获取文本。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace ExtendedComponents
{
    public partial class Scroller : UserControl
    {
        /// <summary>
        /// String list.
        /// </summary>
        string[] m_text = new string[0];

        /// <summary>
        /// Offset for animation.
        /// </summary>
        int m_scrollingOffset = 0;

        /// <summary>
        /// Top part size of text in percents.
        /// </summary>
        int m_topPartSizePercent = 50;

        /// <summary>
        /// Font, which is used to draw.
        /// </summary>
        Font m_font = new Font("Arial", 20, FontStyle.Bold, GraphicsUnit.Pixel);

        /// <summary>
        /// Constructor
        /// </summary>
        public Scroller()
        {
            InitializeComponent();

            // Enables double buffering (to remove flickering) and enables user paint.
            SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);

        }

        /// <summary>
        /// Text to scroll.
        /// </summary>
        public string TextToScroll
        {
            get 
            {
                return string.Join("\n", m_text);
            }
            set 
            {
                string buffer = value;

                // Splits text by "\n" symbol.
                m_text = buffer.Split(new char[1] { '\n' });
            }
        }

        /// <summary>
        /// Timer interval.
        /// </summary>
        public int Interval
        {
            get
            {
                return m_timer.Interval;
            }
            set
            {
                m_timer.Interval = value;
            }
        }

        /// <summary>
        /// Font, which is used to draw.
        /// </summary>
        public Font TextFont
        {
            get
            {
                return m_font;
            }

            set
            {
                m_font = value;
            }
        }

        /// <summary>
        /// Top part size of text in percents (of control width).
        /// </summary>
        public int TopPartSizePercent
        {
            get
            {
                return m_topPartSizePercent;
            }
            set
            {
                if ((value >= 10) && (value <= 100))
                {
                    m_topPartSizePercent = value;
                }
                else
                    throw new InvalidEnumArgumentException("The value must be more than zero. and less than 100.");
            }
        }

        /// <summary>
        /// Paint handler.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnPaint(object sender, PaintEventArgs e)
        {
            // Sets antialiasing mode for better quality.
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

            // Prepares background.
            e.Graphics.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);

            // Creates GraphicsPath for text.
            GraphicsPath path = new GraphicsPath();

            // Visible lines counter;
            int visibleLines = 0;

            for (int i = m_text.Length - 1; i >= 0; i--)
            {

                Point pt = new Point((int)((this.ClientSize.Width - e.Graphics.MeasureString(m_text[i], m_font).Width) / 2),
                    (int)(m_scrollingOffset + this.ClientSize.Height - (m_text.Length - i) * m_font.Size));

                // Adds visible lines to path.
                if ((pt.Y + this.Font.Size > 0) && (pt.Y < this.Height))
                {
                    path.AddString(m_text[i], m_font.FontFamily, (int)m_font.Style, m_font.Size,
                        pt, StringFormat.GenericTypographic);

                    visibleLines++;
                }

                String drawString = m_text[i];
                Font drawFont = new Font("Arial", 16);
                SolidBrush drawBrush = new SolidBrush(Color.Red);
                e.Graphics.DrawString(drawString, drawFont, drawBrush, pt);

            }

            // For repeat scrolling.
            if ((visibleLines == 0) && (m_scrollingOffset < 0))
            {
                m_scrollingOffset = (int)this.Font.SizeInPoints * m_text.Length;
            }



            int topSizeWidth = (int)(this.Width * m_topPartSizePercent / 100.0f);

            // Wraps Graphics path from rectangle to trapeze.
            path.Warp(
                new PointF[4] 
                { 
                    new PointF((this.Width - topSizeWidth) / 2, 0),
                    new PointF(this.Width - (this.Width - topSizeWidth) / 2, 0),
                    new PointF(0, this.Height),
                    new PointF(this.Width, this.Height)
                },
                new RectangleF(this.ClientRectangle.X, this.ClientRectangle.Y, this.ClientRectangle.Width, this.ClientRectangle.Height),
                null,
                WarpMode.Perspective
                );

            // Draws wrapped path.
            e.Graphics.FillPath(new SolidBrush(this.ForeColor), path);
            path.Dispose();

            // Draws fog effect with help of gradient brush with alpha colors.
            /*using (Brush br = new LinearGradientBrush(new Point(0, 0), new Point(0, this.Height),
                Color.FromArgb(255, this.BackColor), Color.FromArgb(0, this.BackColor)))
            {
                e.Graphics.FillRectangle(br, this.ClientRectangle);
            }*/
        }

        /// <summary>
        /// Starts the animation from the beginning.
        /// </summary>
        public void Start()
        {
            // Calculates scrolling offset.
            m_scrollingOffset = (int)this.Font.SizeInPoints * m_text.Length;
            m_timer.Start();
        }

        /// <summary>
        /// Stops the animation.
        /// </summary>
        public void Stop()
        {
            m_timer.Stop();
        }

        /// <summary>
        /// Timer handler.
        /// </summary>
        private void OnTimerTick(object sender, EventArgs e)
        {
            // Changes the offset.
            m_scrollingOffset--;

            // Repaints whole control area.
            Invalidate();
        }


    }
}

我在onpaint事件中添加了这个部分,但这会将整个文本绘制成红色。 如何以不同的颜色在文本中绘制每一行?

String drawString = m_text[i];
Font drawFont = new Font("Arial", 16);
SolidBrush drawBrush = new SolidBrush(Color.Red);
e.Graphics.DrawString(drawString, drawFont, drawBrush, pt);

2 个答案:

答案 0 :(得分:2)

您必须分别绘制每一行。使用MeasureString帮助您找出每行之间的填充。

http://msdn.microsoft.com/en-us/library/system.drawing.graphics.measurestring(v=vs.110).aspx

答案 1 :(得分:1)

随机生成颜色并将其传递给SolidBrush

Random r = new Random();
for (int i = m_text.Length - 1; i >= 0; i--)
{

    Point pt = new Point((int)((this.ClientSize.Width - e.Graphics.MeasureString(m_text[i], m_font).Width) / 2),
        (int)(m_scrollingOffset + this.ClientSize.Height - (m_text.Length - i) * m_font.Size));

    // Adds visible lines to path.
    if ((pt.Y + this.Font.Size > 0) && (pt.Y < this.Height))
    {
        path.AddString(m_text[i], m_font.FontFamily, (int)m_font.Style, m_font.Size,
            pt, StringFormat.GenericTypographic);

        visibleLines++;
    }


    Color c = Color.FromArgb(r.Next(0, 255), r.Next(0, 255), r.Next(0, 255));
    Font drawFont = new Font("Arial", 16);  
    e.Graphics.DrawString( m_text[i], drawFont, new SolidBrush(c), pt);
}