用C#自制 动态桌面 黑客帝国 流动字符

           今天同学给我一个可以在桌面下雪的动态桌面软件. 很有意思.与普通的动态桌面不同的,它并非在桌面设置背景Web页. 而是直接画在整个屏幕上的. 如图.如果仿照其设计思路,那就可以做一个其它类型的动态桌面程序.

那就做一个黑客帝国中流动文字程序.大家先看一下效果,觉得值得看,再往下看.下载完整源码

要做的第一步是,得到一个包含各国文字的随机字符串.  这个好办,可以根据各国文字的代码页,得到编码器,并用其编码得到随机字符串.

         /// <summary>
        
/// Name:ks_c_5601-1987  DisplayName:Korean  CodePage:949
        
/// </summary>

         private  Encoding korean  =  Encoding.GetEncoding( 949 );      
        
/// <summary>
        
/// Name:gb2312  DisplayName:Chinese Simplified (GB2312)  CodePage:936
        
/// </summary>

         private  Encoding chs  =  Encoding.GetEncoding( 936 );

        
/// <summary>
        
/// Name:big5  DisplayName:Chinese Traditional (Big5)  CodePage:950
        
/// </summary>

         private  Encoding cht  =  Encoding.GetEncoding( 950 );

第二步,准备用到的本地函数:因为一个字符串显示完了,后有逐字删除的效果,所以对,绘过区域要进行重绘.还要获是屏幕窗口句柄, 如果只在桌面绘制,需要得到包含图标窗口的句柄.

         /// <summary>
        
/// 获得桌面含图标窗口的句柄,不是全屏窗口句柄
    
/// </summary>
        
/// <returns></returns>

         public   static  IntPtr GetDesktopIconWnd()
        
{
            IntPtr hResult;
            hResult 
= FindWindow("ProgMan"null);
            hResult 
= GetWindow(hResult, 5);
            hResult 
= GetWindow(hResult, 5);
            
return hResult;
        }

第三步,有准备多种色彩的随机刷子数组.

第四步,绘制字符串.字符串对像(Texter)它包含了一个郁机位置,字符就从这里开始以竖直方式绘制,为了实现字符串向下流动的效果,设计一个绘制字符串的机制. 有这了个字符串对象集合(Drawer),它有一个绘制字符串的时钟周期.在一个时钟周期内,它迭代它所包有字符串对象,并调用字符串对象的void Draw(Graphics g)方法.  在字符串对象绘制自已的字符串时,一个周期内只绘制两个字符,第一个为随机色,第二个为白色. 当在下一个周期绘制时,会把上一次的白色字符重新绘制成随机色,把第下一个字符绘制成白色.如此下去,就有一个白色字符下坠的效果.

         /// <summary>
        
/// 字符串增长绘制
        
/// </summary>
        
/// <param name="g"></param>

         private   void  Increase(Graphics g)
        
{
            
float charY = location.Y + drawedChar * CHARHEIGHT;
            
if (drawedChar >= text.Length || charY >= height)
            
{
                increaseDrawText 
= false;
                
return;
            }


            
string chart = string.Format("{0}", text[drawedChar]);
            g.DrawString(chart, font, RndBrush.DrawBursh, 
new PointF(location.X, charY));

            drawedChar
++;
            charY 
= location.Y + drawedChar * CHARHEIGHT;
            
if (drawedChar < text.Length - 1)//绘制白色字
            {
                chart 
= string.Format("{0}", text[drawedChar]);
                g.DrawString(chart, font, RndBrush.White, 
new PointF(location.X, charY));
            }

        }

当字符串对象把自已的字符串绘制完后,开始从上到下,一个周期内删除一个字符,直到"删除"完毕.删除操作,并不是真正的删除,而是指定字符所在的区域为无效,并让窗体重绘该区域. 也许你认为让窗口每次都重绘不就得了,可以是可以,但是你会看到屏幕一直在闪,这就不爽了.所以此举有副作用,弃之.

当字符删除完后,它的一个生命周期结束,重新生成新的随机字符串,和随机位置.然后重复上面的操作.

         /// <summary>
        
/// 字符串减少绘制
        
/// </summary>
        
/// <param name="g"></param>

         private   void  Reduce(Graphics g)
        
{
            
int charY = location.Y + redeceChar * CHARHEIGHT;
            redeceChar
++;
            
if (redeceChar >= drawedChar || charY >= height)
            
{
                
this.text = Texter.rndText.GetRandomText(rnd.Next(minLeng, maxLeng));
                
this.location = RndLocation;
                
this.increaseDrawText = true;
                
this.drawedChar = this.redeceChar = 0;
                
return;
            }

            invalidateEventArgs.Region 
= new Rectangle(location, new Size(20, charY));
            OnRegionInvalidate(invalidateEventArgs);
        }


        
/// <summary>
        
/// 字符所在的区域无效
        
/// </summary>
        
/// <param name="e"></param>

         protected   void  OnRegionInvalidate(InvalidateEventArgs e)
        
{
            
if (RegionInvalidate != null)
            
{
                RegionInvalidate(
this, e);
            }

        }

 

         /// <summary>
        
/// 重绘字符区域
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>

         void  t_RegionInvalidate( object  sender, InvalidateEventArgs e)
        
{
            Rect rect 
= Rect.FromXYWH(e.Region.X, e.Region.Y, e.Region.Width, e.Region.Height);
            NativeMethod.RedrawWindow(hWnd, 
ref rect, IntPtr.Zero,
                RedrawFlag.RDW_ERASE
                
| RedrawFlag.RDW_INVALIDATE
                
| RedrawFlag.RDW_ERASENOW
                
| RedrawFlag.RDW_ALLCHILDREN);
        }

第五步,绘制器(字符串对象集合Drawer),一个时钟周期内迭代字符串对像,并绘制.

构造函数.

         public  Drawer(IntPtr hWnd)
        
{
            maxLeng 
= 15;
            minLeng 
= 5;
            velocity 
= 25;
            
this.textCount = 50;
            
this.hWnd = hWnd;
            Rect rect 
= new Rect();
            NativeMethod.GetWindowRect(hWnd, 
ref rect);
            areaSize 
= rect.Size;

            
this.graphics = Graphics.FromHdc(NativeMethod.GetWindowDC(hWnd));

            texters 
= new List<Texter>(128);
            timerDraw 
= new Timer();
            timerDraw.Interval 
= velocity;
            timerDraw.Tick 
+= new EventHandler(timerDraw_Tick);

            timerBalanceTexter 
= new Timer();
            timerBalanceTexter.Interval 
= 1000;
            timerBalanceTexter.Tick 
+= new EventHandler(timerBalanceTexter_Tick);
        }
         private   void  timerDraw_Tick( object  sender, EventArgs e)
        
{
            
this.Draw(this.graphics);
        }

        
private   void  Draw(Graphics g)
        
{
            
foreach (Texter t in this.texters)
            
{
                t.Draw(g);
            }

        }

这样就做完了. 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值