Windows Phoneアプリケーション開発入門

第15回 Windows Phoneでグラデーションのボタンを作ってみよう!(2)

この記事を読むのに必要な時間:およそ 6 分

様々な図形のグラデーションを描画するための準備

前記のDrawGradientEllipseメソッドの処理では円形にしか対応していません。今後簡単に図形を足して行けるようにGraphicsExtensionクラスを書き換えてみました。

  using System;
  using System.Linq;
  using System.Collections.Generic;
  using System.Text;
  
  using System.Drawing;
  using System.Drawing.Imaging;
  
  namespace GradientionSample
  {
      public class GraphicsExtension
      {
          // 透過用のキーカラー
          public static Color KeyColor = Color.FromArgb(255, 0, 255);

          // クリッピング用画像描画デリゲート定義
          private delegate void InnderDrawFunction(Graphics g, 
              Rectangle rc, Color fillColor, Color borderColor);

          // グラデーション描画メソッド(共通処理)
          private static void InnerDrawGradient(Graphics g, Rectangle rc, 
              Color startColor, Color endColor, Color borderColor, 
              FillDirection gradientType, InnderDrawFunction func)
          {
              // クリッピング用の色の設定
              Color clippingColor = Color.Green;

              Rectangle rect = new Rectangle(0, 0, rc.Width, rc.Height);

              // グラデーションを描画するイメージの生成
              Bitmap gradientImage = new Bitmap(rc.Width, rc.Height,
                  PixelFormat.Format16bppRgb565);
              Graphics gxGradient = Graphics.FromImage(gradientImage);

              // グラデーションを描画する
              GradientFill.Fill(gxGradient, rect,
                  startColor, endColor, FillDirection.TopToBottom);

              // 任意の図形でグラデーションを切り抜く為のイメージの生成
              Bitmap tempImage = new Bitmap(rc.Width, rc.Height,
                  PixelFormat.Format16bppRgb565);

              // クリッピング用の図形を描画するdelegateを呼ぶ
              Graphics gxTemp = Graphics.FromImage(tempImage);
              func(gxTemp, rect, clippingColor, borderColor);

              // グラデーションイメージに対して、
              // クリッピング用のイメージを、緑色の透過色を使用して上書きする
              ImageAttributes clippingAttr = new ImageAttributes();
              clippingAttr.SetColorKey(clippingColor, clippingColor);
              gxGradient.DrawImage(tempImage,
                  rect, 0, 0, rect.Width, rect.Height,
                  GraphicsUnit.Pixel, clippingAttr);

              // グラデーションの掛かった図形を描画する
              ImageAttributes attrib = new ImageAttributes();
              attrib.SetColorKey(KeyColor, KeyColor);
              g.DrawImage(gradientImage, rc, 0, 0, 
                  gradientImage.Width, gradientImage.Height,
                  GraphicsUnit.Pixel, attrib);

              // Clean up
              gxTemp.Dispose();
              tempImage.Dispose();
              gxGradient.Dispose();
              gradientImage.Dispose();
          }

          // グラデーションが掛かった円形を描画する
          public static void DrawGradientEllipse(
              Graphics g, Rectangle rc,
              Color startColor, Color endColor, Color borderColor,
              FillDirection gradientType)
          {
              InnerDrawGradient(g, rc, startColor, 
                  endColor, borderColor, gradientType, 
                  new InnderDrawFunction(_DrawEllipse));
          }

          // クリッピング用の図形を描画するメソッド
          private static void _DrawEllipse(Graphics g, 
              Rectangle rc, Color fillColor, Color borderColor)
          {
              // 描画用オブジェクトの取得
              SolidBrush fillBrush = new SolidBrush(fillColor);
              Pen borderPen = new Pen(borderColor);

              // 背景は透過色でクリアしておく
              g.Clear(KeyColor);

              // 円を描く
              g.FillEllipse(fillBrush, rc);

              // ボーダーを描画する
              if (borderColor != Color.Empty)
              {
                  g.DrawEllipse(borderPen, rc);
              }

              // 描画用オブジェクトの解放
              fillBrush.Dispose();
              fillBrush = null;
              borderPen.Dispose();
              borderPen = null;
          }
      }
  }

publicにするDrawXXXメソッドと,内部で緑色のクリッピング用の図形を描画するprivateな_DraXXXメソッドを書けば,円形と同様にグラデーションの掛かった図形を描画することができます。

グラデーションの掛かった星形を描画する

描画用メソッドとクリッピング用の図形を描画するメソッドを用意します。下記のメソッドをGraphicsExtensionクラスに追加してください。

// グラデーションが掛かった円形を描画する
public static void DrawGradientStar(
    Graphics g, Rectangle rc,
    Color startColor, Color endColor, Color borderColor,
    FillDirection gradientType)
{
    InnerDrawGradient(g, rc, startColor,
        endColor, borderColor, gradientType,
        new InnderDrawFunction(_DrawStar));
}

// クリッピング用の図形を描画するメソッド
private static void _DrawStar(Graphics g,
    Rectangle rc, Color fillColor, Color borderColor)
{
    // 描画用オブジェクトの取得
    SolidBrush fillBrush = new SolidBrush(fillColor);
    Pen borderPen = new Pen(borderColor);

    // 背景は透過色でクリアしておく
    g.Clear(KeyColor);

    // 星形を描画する
    Point[] apt = new Point[5];
    for (int i = 0; i < apt.Length; i++)
    {
        double dAngle = (i * 0.8 - 0.5) * Math.PI;
       
        apt[i] = new Point(
            (int)(rc.Width * (0.50 + 0.48 * Math.Cos(dAngle))),  
            (int)(rc.Height * (0.50 + 0.48 * Math.Sin(dAngle))));

    }
    g.FillPolygon(fillBrush, apt);

    // ボーダーを描画する
    if (borderColor != Color.Empty)
    {
        g.DrawPolygon(borderPen, apt);
    }

    // 描画用オブジェクトの解放
    fillBrush.Dispose();
    fillBrush = null;
    borderPen.Dispose();
    borderPen = null;
}

呼び出し元のForm.OnPaintメソッド内にて,DrawGradientStarメソッドを呼び出しています。

protected override void OnPaint(PaintEventArgs e)
{
    // グラデーションを描画する図形を設定する
    Rectangle rect = new Rectangle();
    rect.Width = this.Width / 2;
    rect.Height = this.Height / 2;
    rect.X = (this.Width - rect.Width) / 2;
    rect.Y = (this.Height - rect.Height) / 2;

    // グラデーション開始色
    Color startColor = Color.Red;
    // グラデーション終了色
    Color endColor = Color.Black;
    // グラデーションの方向
    FillDirection type = FillDirection.TopToBottom;

    // グラデーションの掛かった星形を描く
    GraphicsExtension.DrawGradientStar(e.Graphics,
        rect, startColor, endColor, Color.Empty, type);
}

実行の結果,画面中央にグラデーションの掛かった星形が描画されていれば完成です。

グラデーションの掛かった星形

グラデーションの掛かった星形

さいごに

サンプルコードを実行しながら,.NET Compact Frameworkからどうやってグラデーションを使えばよいのかを知って頂ければ幸いです。特に今回のグラデーションが掛かった任意の図形の作り方は,活用のしがいがあると思います。

次回は,今回のことを応用して角丸ボタンの見た目の部分を作りたいと思います。

以上で今回は終わりです。ありがとうございました。

著者プロフィール

和田健司(わだけんじ)

1982年10月12日生まれ。大阪で働くプログラマ。Microsoft MVP for Device Application Development(Jul 2010 - Jun 2011)。Windows Mobileに傾倒し今に至る。Windows Mobile向けのTipsを書いています。iPhoneアプリ開発を始めました。嫌いな食べ物はカレー。

URL: http://ch3cooh.jp/
Blog: http://d.hatena.ne.jp/ch3cooh393/

コメント

コメントの記入