Hatena::ブログ(Diary)

酢ろぐ(ch3cooh.jp) RSSフィード


CH3COOH(酢酸)の実験室
Baseball Japan / ○○時計 for WP7 / for WM
Windows Phone 7 開発 Tips

2010-05-22

.NET Compact Frameworkからグラデーションを使う

Windows Mobileというか.NET Compact Frameworkでグラデーションをするのには工夫が必要。工夫って言ってもよくあるP/Invokeを使います。これってトリビアになりませんかね?

グラデーションする為には、ネイティブのGradientFill関数を使います。CFからは使えません。ソースは、MS。まずは、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を使えば、グラデーションなんて一瞬なんだけどね。はやくMSWindows Phone 7を日本で発売すべき。

BOOKSCANはじまってた

噂のBOOKSCAN(ブックスキャン) 本・蔵書電子書籍化サービス - 大和印刷がサービス開始していた。結構値段の変更があるなぁ。うちの分厚い技術書関係は、全部3冊分の値段を払わないといけないっぽい。

うちの狭い部屋の中だけでも確実にn百冊と書籍があるので捨てていきたい。誰かスキャンするバイトを請け負ってくれないかなぁ。早く電子書籍化可能な環境を整えたい。