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

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

はじめに

Windows Mobile 6.5の標準のボタンは、イマドキのスマートフォンにしてはシンプルすぎます。コンシューマーにウケるには、グラデーションのかかったボタンが必要です。前回は、図形を描画する方法をご紹介致しましたね。前回の内容から少し進んで、今回からはグラデーションを使った図形の描画の仕方、グラデーションのかかったボタンの実装についてご紹介したいと思います。

Windows Phone 7では、至極簡単にグラデーションのかかったボタンを描画することができますので、後回しにしてしまって、先にWindows Mobile 6.5での実装をしてみましょう。

グラデーションを描画するための前準備

デスクトップ版の.NET Frameworkアプリケーションでは、線形的なグラデーションを描画するには、矩形の描画時にSystem.Drawing.Drawing2D名前空間のLinearGradientBrushオブジェクトを使用すれば、特別なことをせずグラデーションのかかった図形を描画することができます。

.NET Compact Frameworkでは、LinearGradientBrushは削除されているクラスですので、残念ながら簡単にグラデーションを扱うことができません。ただ、WIN32APIのGradientFill関数は存在していますので、P/Invokeを用いて.NET Compact Framework上からグラデーションを扱うことができます。

さて、まずはグラデーションを描画するための前準備として、P/Invokeの宣言とヘルパークラスの実装をしてみましょう。ここでは、プロジェクト名を「GradientionSample」で新規作成したとします。

P/Invoke宣言クラスを実装する

最初に、WIN32APIのP/Invoke宣言をまとめたクラスを実装します。プロジェクトを右クリックして、⁠追加⁠⁠→⁠クラス]で新しいクラスを作成します。名前はWIN32APIのネイティブ関数を使うためにP/Invoke宣言するクラスなので、⁠Win32.cs」とでもしましょう。

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

using System.Drawing;
using System.Runtime.InteropServices;

namespace GradientionSample
{
    public sealed class Win32
    {
        [DllImport("coredll.dll", SetLastError = true, EntryPoint = "GradientFill")]
        public extern static bool GradientFill(
            IntPtr hdc, TRIVERTEX[] pVertex, uint dwNumVertex, 
            GRADIENT_RECT[] pMesh, uint dwNumMesh, uint dwMode);
        
        public struct TRIVERTEX
        {
            public int x;
            public int y;
            public ushort Red;
            public ushort Green;
            public ushort Blue;
            public ushort Alpha;
            
            public TRIVERTEX(int x, int y, Color color)
                : this(x, y, color.R, color.G, color.B, color.A)
            {
            }
           
            public TRIVERTEX(
                int x, int y,
                ushort red, ushort green, ushort blue,
                ushort alpha)
            {
                this.x = x;
                this.y = y;
                this.Red = (ushort)(red << 8);
                this.Green = (ushort)(green << 8);
                this.Blue = (ushort)(blue << 8);
                this.Alpha = (ushort)(alpha << 8);
            }
        
        }
        public struct GRADIENT_RECT
        {
            public uint UpperLeft;
            public uint LowerRight;
            public GRADIENT_RECT(uint ul, uint lr)
            {
                this.UpperLeft = ul;
                this.LowerRight = lr;
            }
        }
        
        public enum GRADIENT_FILL : int
        {
            /// <summary>
            /// 水平方向のグラデーション
            /// </summary>
            GRADIENT_FILL_RECT_H = 0x00000000,
            
            /// <summary>
            /// 縦方向のグラデーション
            /// </summary>
            GRADIENT_FILL_RECT_V = 0x00000001,
            
            /// <summary>
            /// Windows CEではサポートされていません
            /// </summary>
            GRADIENT_FILL_TRIANGLE = 0x00000002
        }
    }
}

実際にグラデーションを描画するGradientFill関数です。

[DllImport("coredll.dll", SetLastError = true, EntryPoint = "GradientFill")]
public extern static bool GradientFill(
    IntPtr hdc, TRIVERTEX[] pVertex, uint dwNumVertex, 
    GRADIENT_RECT[] pMesh, uint dwNumMesh, uint dwMode);

左上と右下にある頂点の座標と塗りつぶしモードを指定して、GradientFill関数を呼び出しグラデーションを描画します。

「pVertex」では座標と色を指定するかを指定します。⁠pMesh」はpVertexで指定した配列のインデックスを指定します。⁠dwMode」は、どの塗りつぶしモードを使用するかを指定します。

GRADIENT_FILL_RECT_H左辺から右辺までの領域に色を挿入し塗りつぶします
GRADIENT_FILL_RECT_V上辺から下辺までの領域に色を挿入し塗りつぶします
GRADIENT_FILL_TRIANGLE指定した点から指定した点までの領域に色を挿入して塗りつぶすことができますが、Windows CE系(Windows Mobile含む)ではサポートされていません

GradientFill関数を呼び出すヘルパークラス

[追加⁠⁠→⁠クラス]で新しいクラスを作成します。名前はGradientFill関数を呼び出すヘルパークラスなので、⁠GradientFill.cs」とでもしましょう。

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

using System.Drawing;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace GradientionSample
{
    public enum FillDirection
    {
        // 水平にグラデーションで塗りつぶします
        LeftToRight = Win32.GRADIENT_FILL.GRADIENT_FILL_RECT_H,
        
        // 垂直にグラデーションで塗りつぶします
        TopToBottom = Win32.GRADIENT_FILL.GRADIENT_FILL_RECT_V
    }
    
    public sealed class GradientFill
    {
        public static bool Fill(
            Graphics gr, Rectangle rc,
            Color startColor, Color endColor,
            FillDirection fillDir)
        {
            // 頂点の座標と色を指定
            Win32.TRIVERTEX[] tva = new Win32.TRIVERTEX[2];
            tva[0] = new Win32.TRIVERTEX(rc.X, rc.Y, startColor);
            tva[1] = new Win32.TRIVERTEX(rc.Right, rc.Bottom, endColor);
            
            // どのTRIVERTEXの値を使用するかインデックスを指定
            Win32.GRADIENT_RECT[] gra
                = new Win32.GRADIENT_RECT[] { new Win32.GRADIENT_RECT(0, 1) };
            
            // GradientFill関数の呼び出し
            IntPtr hdc = gr.GetHdc();
            bool b = Win32.GradientFill(
                hdc, tva, (uint)tva.Length,
                gra, (uint)gra.Length, (uint)fillDir);
            gr.ReleaseHdc(hdc);
            return b;
        }
    }
}

このヘルパークラスを使用すれば、Fillメソッドにグラデーションを描画する矩形領域、開始色、終了色、方向を指定するだけで済みます。

グラデーションを使ってみよう

P/Invokeの宣言と、グラデーションを描画するためのヘルパークラスの実装が終りました。さて、実際にグラデーションを描画しましょう。第12回で紹介したFormのOnPaintをオーバーライドした中で、先程のヘルパークラスのメソッドを使用しています。

protected override void OnPaint(PaintEventArgs e)
{
    // グラデーションを描画する矩形を設定する
    Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
    // グラデーション開始色
    Color startColor = Color.Red;
    // グラデーション終了色
    Color endColor = Color.Black;
    // グラデーションの方向
    FillDirection type = FillDirection.TopToBottom;
    
    // グラデーションを書く
    GradientFill.Fill(e.Graphics, rect, startColor, endColor, type);
}

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

指定した座標と高さ幅を指定して、赤色の上から黒色の下へ向けてグラデーションをかけています。

垂直モードのグラデーション
垂直モードのグラデーション

上記のコードは、上から下へのグラデーションですが、FillDirectionの値を「FillDirection.LeftToRight」に変えることで、左から右へのグラデーションに変更できます。

水平モードのグラデーション
水平モードのグラデーション

さいごに

.NET Compact Frameworkアプリケーションから簡単にグラデーションを使うためのヘルパークラスを作成して、実際にForm上でグラデーションさせてみました。

グラデーションを使って様々な図形を描画する時には、少し手間ですが段階を追って描画する必要があります。次回は、グラデーションさせた円形などの図形を描画してみましょう。

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

おすすめ記事

記事・ニュース一覧