Windows Mobileの、さらに.NET Compact Frameworkを使って、グラデーションをするのには工夫が必要です。工夫って言ってもよくあるP/Invokeを使います。
グラデーションする為には、.NET Compact Frameworkからは使えませんので、ネイティブのGradientFill関数を使います。まずはGradientFillを使うためにP/Invokeする為に定義をします。
以下にサンプルコードを示します。
グラデーションを描画する
ネイティブ関数とやり取りする為の構造体を定義
public sealed class Win32 { 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 struct GRADIENT_TRIANGLE { public uint Vertex1; public uint Vertex2; public uint Vertex3; public GRADIENT_TRIANGLE(uint v1, uint v2, uint v3) { this.Vertex1 = v1; this.Vertex2 = v2; this.Vertex3 = v3; } } [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 const int GRADIENT_FILL_RECT_H = 0x00000000; public const int GRADIENT_FILL_RECT_V = 0x00000001; // Not supported on Windows CE: public const int GRADIENT_FILL_TRIANGLE = 0x00000002; }
次にP/InvokeしたGradientFill関数を使いやすくするヘルパーメソッドを作ります。ちなみにGRADIENT_FILL_TRIANGLEは、Windows CEでは使えません。縦方向と横方向限定。いい感じに組み合わせて頑張りましょう。
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); Win32.GRADIENT_RECT[] gra = new Win32.GRADIENT_RECT[] { new Win32.GRADIENT_RECT(0, 1)}; IntPtr hdc = gr.GetHdc(); bool b; b = Win32.GradientFill( hdc, tva, (uint)tva.Length, gra, (uint)gra.Length, (uint)fillDir); System.Diagnostics.Debug.Assert(b, string.Format( "GradientFill failed: {0}", System.Runtime.InteropServices.Marshal.GetLastWin32Error())); gr.ReleaseHdc(hdc); return b; } } public enum FillDirection { // 水平にグラデーションで塗りつぶします LeftToRight = Win32.GRADIENT_FILL_RECT_H, // 垂直にグラデーションで塗りつぶします TopToBottom = Win32.GRADIENT_FILL_RECT_V }
20msとか短いピッチで再描画をかけるには、グラデーションは割と時間がかかるのでキャッシュした方が良さそう。
Expression Blendを使えば、グラデーションなんて一瞬なんだけどね。はやくMSはWindows Phone 7を日本で発売すべき。