главная продукты downloads форум тех. поддержка

 

Главная страница

GDI+ FAQ: Drawing text with a drop shadow effect

 

GDI+'s graphics abilities are excellent for text and graphical "special effects".  One of the nicer effects is to put a drop shadow on text.

 

Many simple text effects simply involve drawing the text two or more times using different colours and positions. Drop shadows however take advantage of GDI+'s antialiasing capabilities to produce alpha blended shadows with delicious umbra and penumbra shadows.

 

The trick to this is to first draw the text smaller than you want it to appear on the drawing surface and then blow it up by stretching it.

 

The steps to take are as follows:

 

  • Create a Bitmap in memory who's dimensions are some sub-multiple of the current window (for this example I use a ¼ size)
  • Set up a matrix to make the text ¼ of the size and move it ¼ of the distance that you want the drop shadow to be from the "original"
  • Draw the text to the bitmap using an antialiased drawing mode and a pen that has an alpha component (say 50% transparency). Remember that when newly created in memory, bitmaps are already 100% transparent so the bits we add make non-transparent areas in the image which show up as artifacts on the screen after blitting..
  • Blit the bitmap to the main screen, expanding it by 4:1 in both directions using a HighQualityBicubic interpolation mode. This is very important because the bicubic sampling makes the edges of the text fuzzy and indistinct and provide the umbra and penumbra effect.
  • Finally, draw the original text onto the main drawing surface. Once again an antialiased drawing mode should be used to ensure correct registration of the text with its shadow. For this purpose the TextRenderingHint.Antialias is best.

  

After completing these steps, an effect similar to that seen in Figure 1 is possible.

 

 

Figure 1.

 

The application that produced this effect is listed in its entirety below. The Form1_Paint event handler is the bit that does the work.

 

using System;

using System.Drawing;

using System.Drawing.Text;

using System.Drawing.Drawing2D;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

 

namespace textdropshadow

{

       /// <summary>

       /// Summary description for Form1.

       /// </summary>

       public class Form1 : System.Windows.Forms.Form

       {

              /// <summary>

              /// Required designer variable.

              /// </summary>

              private System.ComponentModel.Container components = null;

 

              public Form1()

              {

                     //

                     // Required for Windows Form Designer support

                     //

                     InitializeComponent();

 

                     this.SetStyle(ControlStyles.ResizeRedraw,true);

              }

 

              /// <summary>

              /// Clean up any resources being used.

              /// </summary>

              protected override void Dispose( bool disposing )

              {

                     if( disposing )

                     {

                           if (components != null)

                           {

                                  components.Dispose();

                           }

                     }

                     base.Dispose( disposing );

              }

 

              #region Windows Form Designer generated code

              /// <summary>

              /// Required method for Designer support - do not modify

              /// the contents of this method with the code editor.

              /// </summary>

              private void InitializeComponent()

              {

                     //

                     // Form1

                     //

                     this.AutoScaleBaseSize = new System.Drawing.Size(16, 36);

                     this.BackColor = System.Drawing.Color.White;

                     this.ClientSize = new System.Drawing.Size(376, 293);

                     this.Font = new System.Drawing.Font("Tahoma", 21.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));

                     this.Name = "Form1";

                     this.Text = "Form1";

                     this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint);

 

              }

              #endregion

 

              /// <summary>

              /// The main entry point for the application.

              /// </summary>

              [STAThread]

              static void Main()

              {

                     Application.Run(new Form1());

              }

 

              protected override void OnPaintBackground(PaintEventArgs e)

              {

                     LinearGradientBrush b=new LinearGradientBrush(this.ClientRectangle,Color.Blue,Color.AliceBlue,90f);

                     e.Graphics.FillRectangle(b,this.ClientRectangle);

                     b.Dispose();

              }

 

              private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)

              {

                     //Make a small bitmap

                     Bitmap bm=new Bitmap(this.ClientSize.Width/4,this.ClientSize.Height/4);

                     //Get a graphics object for it

                     Graphics g=Graphics.FromImage(bm);

                     // must use an antialiased rendering hint

                     g.TextRenderingHint=TextRenderingHint.AntiAlias;

                     //this matrix zooms the text out to 1/4 size and offsets it by a little right and down

                     Matrix mx=new Matrix(0.25f,0,0,0.25f,3,3);

                     g.Transform=mx;

                     //The shadow is drawn

                     g.DrawString("Text with a dropshadow",Font,new SolidBrush( Color.FromArgb(128, Color.Black)), 10, 10, StringFormat.GenericTypographic );

                     //Don’t need this anymore

                     g.Dispose();

                     //The destination Graphics uses a high quality mode

                     e.Graphics.InterpolationMode=InterpolationMode.HighQualityBicubic;

                     //and draws antialiased text for accurate fitting

                     e.Graphics.TextRenderingHint=TextRenderingHint.AntiAlias;

                     //The small image is blown up to fill the main client rectangle

                     e.Graphics.DrawImage(bm,this.ClientRectangle,0,0,bm.Width,bm.Height,GraphicsUnit.Pixel);

                     //finally, the text is drawn on top

                     e.Graphics.DrawString("Text with a dropshadow",Font,Brushes.White,10,10,StringFormat.GenericTypographic);

                     bm.Dispose();

              }

       }

}

 

Back to the GDI+ FAQ

 

e-mail:

 

bousoft@mail.ru