Winform 下无闪烁走马灯效果实现

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

namespace ScrollingTextControl
{
    
/// <summary>
    
/// Summary description for ScrollingTextControl.
    
/// </summary>

    [
    ToolboxBitmapAttribute(
typeof(ScrollingTextControl.ScrollingText), "ScrollingText.bmp"),
    DefaultEvent(
"TextClicked")
    ]
    
public class ScrollingText : System.Windows.Forms.Control
    
{
        
private Timer timer;                            // Timer for text animation.
        private string text = "Text";                    // Scrolling text
        private float staticTextPos = 0;                // The running x pos of the text
        private float yPos = 0;                            // The running y pos of the text
        private ScrollDirection scrollDirection = ScrollDirection.RightToLeft;                // The direction the text will scroll
        private ScrollDirection currentDirection = ScrollDirection.LeftToRight;                // Used for text bouncing 
        private VerticleTextPosition verticleTextPosition = VerticleTextPosition.Center;    // Where will the text be vertically placed
        private int scrollPixelDistance = 2;            // How far the text scrolls per timer event
        private bool showBorder = true;                    // Show a border or not
        private bool stopScrollOnMouseOver = false;        // Flag to stop the scroll if the user mouses over the text
        private bool scrollOn = true;                    // Internal flag to stop / start the scrolling of the text
        private Brush foregroundBrush = null;            // Allow the user to set a custom Brush to the text Font
        private Brush backgroundBrush = null;            // Allow the user to set a custom Brush to the background
        private Color borderColor = Color.Black;        // Allow the user to set the color of the control border
        private RectangleF lastKnownRect;                // The last known position of the text

        
public ScrollingText()
        
{
            
// Setup default properties for ScrollingText control
            InitializeComponent();
            
            
//This turns off internal double buffering of all custom GDI+ drawing
            
            Version v 
= System.Environment.Version;

            
if (v.Major < 2)
            
{
                
this.SetStyle(ControlStyles.DoubleBuffer, true);
            }

            
else
            
{
                
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            }

            
            
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            
this.SetStyle(ControlStyles.UserPaint, true);
            
this.SetStyle(ControlStyles.ResizeRedraw, true);

            
//setup the timer object
            timer = new Timer();
            timer.Interval 
= 25;    //default timer interval
            timer.Enabled = true;
            timer.Tick 
+= new EventHandler(Tick);            
        }


        
/// <summary>
        
/// Clean up any resources being used.
        
/// </summary>

        protected override void Dispose( bool disposing )
        
{
            
if( disposing )
            
{
                
//Make sure our brushes are cleaned up
                if (foregroundBrush != null)
                    foregroundBrush.Dispose();

                
//Make sure our brushes are cleaned up
                if (backgroundBrush != null)
                    backgroundBrush.Dispose();

                
//Make sure our timer is cleaned up
                if (timer != null)
                    timer.Dispose();
            }

            
base.Dispose( disposing );
        }


        
Component Designer generated code
    
        
//Controls the animation of the text.
        private void Tick(object sender, EventArgs e)
        
{
            
//update rectangle to include where to paint for new position            
            
//lastKnownRect.X -= 10;
            
//lastKnownRect.Width += 20;            
            lastKnownRect.Inflate(105);

            
//get the display rectangle
            RectangleF refreshRect = lastKnownRect;
            refreshRect.X 
= Math.Max(0, lastKnownRect.X);
            refreshRect.Width 
= Math.Min(lastKnownRect.Width + lastKnownRect.X, this.Width);
            refreshRect.Width 
= Math.Min(this.Width - lastKnownRect.X, refreshRect.Width);

            
//create region based on updated rectangle
            
//Region updateRegion = new Region(lastKnownRect);            
            Region updateRegion = new Region(refreshRect);        
            
            
//repaint the control            
            Invalidate(updateRegion);
            Update();
        }


        
//Paint the ScrollingTextCtrl.
        protected override void OnPaint(PaintEventArgs pe)
        
{
            
//Console.WriteLine(pe.ClipRectangle.X + ",  " + pe.ClipRectangle.Y + ",  " + pe.ClipRectangle.Width + ",  " + pe.ClipRectangle.Height);

            
//Paint the text to its new position
            DrawScrollingText(pe.Graphics);

            
//pass on the graphics obj to the base Control class
            base.OnPaint(pe);
        }


        
//Draw the scrolling text on the control        
        public void DrawScrollingText(Graphics canvas)
        
{
            canvas.SmoothingMode 
= SmoothingMode.HighQuality;
            canvas.PixelOffsetMode 
= PixelOffsetMode.HighQuality;

            
//measure the size of the string for placement calculation
            SizeF stringSize = canvas.MeasureString(this.text, this.Font);
        
            
//Calculate the begining x position of where to paint the text
            if (scrollOn)
            
{
                CalcTextPosition(stringSize);    
            }


            
//Clear the control with user set BackColor
            if (backgroundBrush != null)
            
{
                canvas.FillRectangle(backgroundBrush, 
00this.ClientSize.Width, this.ClientSize.Height);
            }

            
else
            
{
                canvas.Clear(
this.BackColor);
            }


            
// Draw the border
            if (showBorder)
            
{
                
using (Pen borderPen = new Pen(borderColor))
                    canvas.DrawRectangle(borderPen, 
00this.ClientSize.Width - 1this.ClientSize.Height - 1);
            }


            
// Draw the text string in the bitmap in memory
            if (foregroundBrush == null)
            
{
                
using (Brush tempForeBrush = new System.Drawing.SolidBrush(this.ForeColor))
                    canvas.DrawString(
this.text, this.Font, tempForeBrush, staticTextPos, yPos);
            }

            
else
            
{
                canvas.DrawString(
this.text, this.Font, foregroundBrush, staticTextPos, yPos);
            }


            lastKnownRect 
= new RectangleF(staticTextPos, yPos, stringSize.Width, stringSize.Height);            
            EnableTextLink(lastKnownRect);
        }


        
private void CalcTextPosition(SizeF stringSize)
        
{
            
switch (scrollDirection)
            
{
                
case ScrollDirection.RightToLeft:
                    
if (staticTextPos < (-1 * (stringSize.Width)))
                        staticTextPos 
= this.ClientSize.Width - 1;
                    
else
                        staticTextPos 
-= scrollPixelDistance;
                    
break;
                
case ScrollDirection.LeftToRight:
                    
if (staticTextPos > this.ClientSize.Width)
                        staticTextPos 
= -1 * stringSize.Width;
                    
else
                        staticTextPos 
+= scrollPixelDistance;
                    
break;
                
case ScrollDirection.Bouncing:
                    
if (currentDirection == ScrollDirection.RightToLeft)
                    
{
                        
if (staticTextPos < 0)
                            currentDirection 
= ScrollDirection.LeftToRight;
                        
else
                            staticTextPos 
-= scrollPixelDistance;                        
                    }

                    
else if (currentDirection == ScrollDirection.LeftToRight)
                    
{
                        
if (staticTextPos > this.ClientSize.Width - stringSize.Width)
                            currentDirection 
= ScrollDirection.RightToLeft;
                        
else
                            staticTextPos 
+= scrollPixelDistance;                        
                    }

                    
break;
            }
                

            
//Calculate the vertical position for the scrolling text                
            switch (verticleTextPosition)
            
{
                
case VerticleTextPosition.Top:
                    yPos 
= 2;
                    
break;
                
case VerticleTextPosition.Center:
                    yPos 
= (this.ClientSize.Height / 2- (stringSize.Height / 2);
                    
break;
                
case VerticleTextPosition.Botom:
                    yPos 
= this.ClientSize.Height - stringSize.Height;
                    
break;
            }

        }


        
Mouse over, text link logic
        

        
Properties        
    }


    
public enum ScrollDirection
    
{
        RightToLeft,
        LeftToRight,
        Bouncing
    }


    
public enum VerticleTextPosition
    
{
        Top,
        Center,
        Botom
    }

}


注意事项
如果要调整滚动速度,可以通过设置以下两个属性的值来实现
TextScrollSpeed 和 TextScrollDistance
TextScrollSpeed 其实是设置刷新频率,单位是毫秒,这个值越小,滚动速度越快。但刷新频率越高,CPU占用率越高。
TextScrollDistance 是指每次刷新移动的像素点,这个值越大,速度越快,但如果太大,文字滚动看起来就不是特别连贯。
所以在实际应用中我们需要同时调整这两个值,以找到最佳的平衡点
posted on 2008-04-20 21:52  西湖浪子  阅读(726)  评论(0)    收藏  举报