.NetCF 绘制半透明效果

前言

  关键字:.NetCF 半透明、AlphaBlend
 

  用C#开放Windows Mobile刚好满一个月,一直是边看文章边写点小例子,而这些例子里面半透明效果是最让人心动的,本文主要收集和实践了关于.Net CF半透明效果例子,以及自己一点点经验和需要注意的问题。

 

正文

  一、绘制透明标签控件(Label) 
 

    1.1  效果图

 

 

1.2  代码

      1.2.1  实现代码

         ///   <summary>
        
///  透明Label控件
        
///      注意,将Label的Visible设置为false;适合背景为图片(PictureBox)
        
///   </summary>
        
///   <param name="label"></param>
        
///   <param name="g"></param>
         public   static   void  TransparentLabel(Label label, Graphics g)
        {
            Rectangle rect  =  label.Bounds;
            SolidBrush sb  =   new  SolidBrush(label.ForeColor);
            SizeF size;
            
// 计算字符串的位置
             switch  (label.TextAlign)
            {
                
case  ContentAlignment.TopLeft:
                    
break ;
                
case  ContentAlignment.TopCenter:
                    
// 计算字符串长度
                    size  =  g.MeasureString(label.Text, label.Font);
                    rect.X  +=  ( int )((rect.Width  -  size.Width)  /   2 );
                    rect.Y  +=  ( int )((rect.Height  -  size.Height)  /   2 );
                    
break ;
                
case  ContentAlignment.TopRight:
                    size  =  g.MeasureString(label.Text, label.Font);
                    rect.X  +=  rect.Width  -  ( int )size.Width;
                    rect.Y  +=  rect.Height  -  ( int )size.Height;
                    
break ;
            }
            g.DrawString(label.Text, label.Font, sb, rect);
            sb.Dispose();
        }

      1.2.2  调用代码

         private   void  pictureBox1_Paint( object  sender, PaintEventArgs e)
        {
            TransparentLabel( this .label1, e.Graphics);
        } 
 

      1.2.3  代码说明

        虽然本节说的是Label透明化,实际上可以看得出并没有将字透明化,只是"去掉"了Label的背景。这里Label控件充当了保存字符串信息的作用,实际调用DrawString直接画在屏幕上去的。

        a).  因为是Label是在PictureBox上,所以在其Paint事件中绘制Label中的字符串;如果没有PictureBox作为背景,而是直接在Form窗体上,那么把这段代码写到窗体的OnPain中即可。

    1.3  注意问题

       1.3.1  需要将Label的Visiable设置为false!

 

  二、绘制透明图片(PictureBox)

    2.1  效果图

 

 

2.2  代码

      2.2.1  实现代码

         ///   <summary>
        
///  绘制透明图片
        
///   </summary>
        
///   <param name="gxBuffer"></param>
        
///   <param name="barImage"></param>
        
///   <param name="barRect"></param>
        
///   <param name="transp"></param>
         public   static   void  DrawAlpha(Graphics gxBuffer, Image barImage, Rectangle barRect,  byte  transp)
        {
            
using  (Graphics gxSrc  =  Graphics.FromImage(barImage))
            {
                IntPtr hdcDst  =  gxBuffer.GetHdc();
                IntPtr hdcSrc  =  gxSrc.GetHdc();
                BlendFunction blendFunction  =   new  BlendFunction();
                blendFunction.BlendOp  =  ( byte )BlendOperation.AC_SRC_OVER;
                blendFunction.BlendFlags  =  ( byte )BlendFlags.Zero;
                blendFunction.SourceConstantAlpha  =  transp;
                blendFunction.AlphaFormat  =  ( byte ) 0 ;
                AlphaBlend(hdcDst, barRect.Left, barRect.Top, barRect.Size.Width, barRect.Size.Height, hdcSrc,  0 0 , barImage.Width, barImage.Height, blendFunction);
                gxBuffer.ReleaseHdc(hdcDst);
                gxSrc.ReleaseHdc(hdcSrc);
            }
        }

        
///   <summary>
        
///  绘制透明图象
        
///   </summary>
        
///   <param name="hdcDest"> 生成画面的Handle </param>
        
///   <param name="xDest"> 生成画面的x </param>
        
///   <param name="yDest"> 生成画面的y </param>
        
///   <param name="cxDest"> 生成画面的width </param>
        
///   <param name="cyDest"> 生成画面的height </param>
        
///   <param name="hdcSrc"> 原图的Handle </param>
        
///   <param name="xSrc"> 原图的x </param>
        
///   <param name="ySrc"> 原图的y </param>
        
///   <param name="cxSrc"> 原图的width </param>
        
///   <param name="cySrc"> 原图的height </param>
        
///   <param name="blendFunction"> 控制 Alpha 混合的结构 </param>
        
///   <returns></returns>
        [DllImport( " coredll.dll " )]
        
extern   public   static  Int32 AlphaBlend(IntPtr hdcDest, Int32 xDest, Int32 yDest, Int32 cxDest, Int32 cyDest, IntPtr hdcSrc, Int32 xSrc, Int32 ySrc, Int32 cxSrc, Int32 cySrc, BlendFunction blendFunction);

      2.2.2  调用代码

         private   void  pictureBox1_Paint( object  sender, PaintEventArgs e)
        {
            CFControlUtility.DrawAlpha(e.Graphics, pbBar.Image, pbBar.Bounds,  170 );
        }

      2.2.3  代码说明

        a).  transp值为0-255,0为完全透明,255为无透明效果。

    2.3  注意问题

      需要透明效果图片的Visiable设置为false!

 

  三、绘制透明表格

    3.1  效果图

 

 

3.2  实现代码

         private   void  pictureBox1_Paint( object  sender, PaintEventArgs e)
        {
            Bitmap offBitmap  =   new  Bitmap( 100 100 );
            Graphics gxBuffer  =  Graphics.FromImage(offBitmap);
            
// 清空底色
            gxBuffer.Clear( this .BackColor);

            Pen pen  =   new  Pen(Color.DodgerBlue);
            Font font  =   new  Font( " Arial " 10 , FontStyle.Regular);
            SolidBrush brush  =   new  SolidBrush(Color.Black);

            
int  width, height  =   0 ;
            
// 绘制2列4行数据
             for  ( int  i  =   0 ; i  <   4 ; i ++ )
            {
                width  =   0 ;
                
for  ( int  j  =   0 ; j  <   2 ; j ++ )
                {
                    
// 绘制数据
                    gxBuffer.DrawString( " 测试数据 " , font, brush, width, height);

                    width  +=   50 ;
                    
// 绘制竖线
                     if  (i  ==   0 )
                        gxBuffer.DrawLine(pen, width,  0 , width, offBitmap.Height);
                    
                }
                height  +=   25 ;
                
// 绘制横线
                gxBuffer.DrawLine(pen,  0 , height, offBitmap.Width, height);
            }

            brush.Dispose();
            font.Dispose();
            pen.Dispose();
            gxBuffer.Dispose();

            
// 将内存中的图片绘制到界面上来
            DrawAlpha(e.Graphics, offBitmap,  new  Rectangle( 50 100 , offBitmap.Width, offBitmap.Height),  170 );
            
// e.Graphics.DrawImage(offBitmap, 50, 100);
        } 
 

    3.3  代码说明

      a).  这里在内存中绘制了临时图片offBitmap,然后再将临时图片绘制显示到设备上面来的,这样可以极大提高性能,大家可以直接用e.Graphics一笔笔绘制比较看下性能。

      b).  用完绘图对象相关对象之后记得Dispose掉,或者用using代码块。
 

 

  四、 其他
 

    4.1  屏幕闪烁问题

         protected   override   void  OnPaintBackground(PaintEventArgs e)
        {
            
// base.OnPaintBackground(e);        
        }

    4.2  直接用e.Graphics绘制文字+图片的时候可能出现闪烁的问题

      在绘制完文字后再覆盖一张透明度为0的空图片即可,用内存临时图片不会有这问题的。

    4.3  绘制控件透明时,千万记得把控件的Visible设置为false。该控件只是充当绘制信息存储作用,其鼠标事件(Mouse)全部会没有(这不废话- - #,控件都隐藏了),所以要做判断得再PictureBox或窗体的相关事件里面做判断,然后再判断点击的位置来识别到底是否点击的透明控件。

    4.4  Graphics相关方法需要都弄清楚用熟练了,非常有用,比如MeasureString可以计算字符串的长度,可以控制绘制字符串的位置;FillRectangle可以填充矩阵,画行的背景色的时候可以用。

    4.5  如果大规模的绘制透明效果,需要特别注意性能问题,可以采取措施如临时图片、内存缓存数据等。

    4.6  通过取消单色显示来达到透明效果,但是效果不太理想,相关的对象:ImageAttributes。

 

 

结束语
 

   如果被这种透明效果吸引甚至打算在项目中使用,那么要做好吃苦耐劳的准备,大部分控件都要重绘,处理非常多的逻辑判断,比较麻烦- - #。



本文转自over140 51CTO博客,原文链接:http://blog.51cto.com/over140/586572,如需转载请自行联系原作者

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值