zoukankan      html  css  js  c++  java
  • .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, 00, 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(100100);
                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(50100, 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。

    结束语

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

      

    本博相关文章  1.  .netcf 图片区域拷贝[图片切割]
  • 相关阅读:
    反射-特性
    反射-2
    反射-1
    智能楼宇管理实用手册
    山光凝翠,川容如画——太原西山地区的历史营建与遗存
    城市逆向规划建设:基于城市生长点形态与机制的研究
    建筑快题设计50问与100例
    明清建筑二论·斗栱的起源与发展
    建筑工程计量与计价实训教程(甘肃版)
    室内设计手绘快速表现技法火星课堂
  • 原文地址:https://www.cnblogs.com/over140/p/1667645.html
Copyright © 2011-2022 走看看