天天看點

.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);

                case ContentAlignment.TopRight:

                    rect.X += rect.Width - (int)size.Width;

                    rect.Y += rect.Height - (int)size.Height;

            }

            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  實作代碼

        /// 繪制透明圖檔

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

        /// 繪制透明圖象

        /// <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  調用代碼

            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  實作代碼

            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,如需轉載請自行聯系原作者

繼續閱讀