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

Winform 下无闪烁走马灯效果实现
作者:肖波
    最近需要在Winform项目中实现一个走马灯的效果,一开始用了一些办法比如移动Label控件,效果总是不太好,移动文本时总有闪烁的现象。后来找了一个国外的开源控件,应用了一下,效果还不错。仔细阅读了一下代码,发现还有一些地方值得改进,现把代码以及改动说明贴出来,和大家分享。
    控件出处: http://www.codeproject.com/KB/miscctrl/ScrollingTextControlArtic.aspx
    我的改动:
    1、DoubleBuffer 的设置
   原代码中用的是 this.SetStyle(ControlStyles.DoubleBuffer, true); 但一些网友反映这个标志在.net 2.0 以上版本无效。说句老实话,我也不是特别确信,MSDN上也没有说明这一点。在我的.net 2.0 系统中,两种设置的效果似乎没有太多区别。在一个国外网站上找到他们的区别,下面是原文:

ControlStyles == CS
AllPaintingInWMPaint == APWMP
OptimizedDoubleBuffer = ODB
DoubleBuffer = DB

An earlier permutation of the design called for ODB to simply be a combination of DB, APWMP and UserPaint. Through several design changes, the two control styles are nearly synonymous, but they still have differences.  Now that we've broken that, we may consider un-deprecating CS.DB to retain . Here is a more complete summary of the current design:

Mechanism Side effects Other flags required to work Require APWMP? Notes
ControlStyle
.DB

none

APWMP, UserPaint

Yes

We are considering NOT deprecating this flag because ODB isn't an exact replacement for DB.
ControlStyle
.ODB

none

none

No

Works, but without APWMP set you'll buffer foreground and background separately and will still see flicker.
Control
.DoubleBuffered

sets CS.ODB, CS.APWMP

none

No

Works for most mainstream buffering needs. Getter is peculiar in that it only checks CS.ODB.


I'm following up on the need for deprecating CS.DB and Control.DoubleBuffered's getter and will post here.

总之保险起见,还是判一下版本号,下面是判断代码
            Version v  =  System.Environment.Version;

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

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

    2、刷新区域
    原代码中刷新区域是这样设置的
         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);

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

lastKnownRect是文字的整个区域,如果文字较长,这个刷新区域就会比较大,但实际上我们只需要刷新控件显示范围内的区域就可以了。
所以这里改动如下:

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

    2、修改Enabled属性
   
当Enabled设置为false时,原控件依然会滚动,觉得还是不让它滚动更好一些。
    修改代码如下:
        [
        Browsable(
true ),
        CategoryAttribute(
" Behavior " ),
        Description(
" Indicates whether the control is enabled " )
        ]
        
new   public   bool  Enabled
        
{
            
set
            
{
                timer.Enabled 
= value;
                
base.Enabled = value;
            }


            
get
            
{
                
return base.Enabled;
            }

        }

下面给出修改后完整的控件代码,代码原作者为 jconwell,原始代码见前面提到的控件出处

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;               
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值