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

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

世界のWindows Mobile開発者へテクニカルプレビュー端末を提供

本年度のホリデーシーズンにWindows Phone 7が製品リリースされるというのは以前から変わらない話題なのですが、販売後に順次Windows Phone 7端末を全Microsoft社員に配布するとニュースになっていたのはご存知でしょうか。

そのニュースとほぼ同時に、世界中のWindows Mobileアプリケーション開発者に向けて、Windows Phone 7のテクニカルプレビュー端末をリリースしたと発表がありました。このテクニカルプレビュー端末は、ハードウェアパートナーとして発表のあった会社のうち、ASUS・LG電子・Samsungの3社のものが対象となっています(YouTube等の動画共有サイトで、海外の開発者がアップロードしたと思われる動画が少なからず話題となっています⁠⁠。

世界中のWindows Phone開発者には、先行して開発機をリリース、社員にはリリース後に配布と、全社を挙げてWindows Phoneを盛り上げていく意志が伝わってくるようで、Microsoftの本気度が伺えます。

Windows Phone 7アプリケーション開発には、現在「Windows Phone Developer Tools Beta」があり、ほとんどのことをシミュレータ上でまかなうことが可能です。逆に実機でないと実現が不可能なこととしては、今までマルチタスクであったWindows Mobileプログラミングでは気にしなくてもよかった競合対策や、各種センサーを使ってのデバイスプログラミングなどでしょうか。そのうち本連載にて取り扱えたらと思います。

はじめに

さて、前回はボタンを表示させました。しかし、単に表示しただけでしたので、ボタンをタップしても、キーボードでフォーカスが当たっても何も変化がありませんでした。

前回実装した通常時の表示
前回実装した通常時の表示

これでは寂しいので、ユーザー操作に対して標準のボタンの表示を変えてみましょう。

ボタンには以下のような状態があります。

  • フォーカスが当っている状態
  • ボタンが押されている状態

今回は、残りのフォーカスが当たっている状態、ボタンが押されている状態をGradientionButtonクラスに実装していきましょう。

ボタンの描画メソッドを修正する

まず、ボタンを描画させるDrawButtonメソッドを、ボタン押下時とフォーカス時に変更していきましょう。pressedがTRUEの場合には、グラデーションの色を反転させます。focusedがTRUEの場合には、ボタンの枠を太くしました。

private void DrawButton(Graphics g, bool pressed, bool focused)
{
    // ボタンの背景を描画
    Pen backLinePen;
    if (!focused)
    {
        backLinePen = new Pen(Color.Black);
    }
    else
    {
        // フォーカスが当たっている場合は、枠線を太く描画する
        backLinePen = new Pen(Color.Black, 2.5f);
    }

    // DrawRectangleメソッドで線を描画するが
    // 線の太さを考慮して幅と高さから引く
    Rectangle lineRect = new Rectangle();
    lineRect.X = ClientRectangle.X + (int)backLinePen.Width;
    lineRect.Y = ClientRectangle.Y + (int)backLinePen.Width;
    lineRect.Width = ClientRectangle.Width - (int)backLinePen.Width * 2;
    lineRect.Height = ClientRectangle.Height - (int)backLinePen.Width * 2;

    g.FillRectangle(new SolidBrush(Color.DimGray), ClientRectangle);
    g.DrawRectangle(backLinePen, lineRect);

    // ボタンの表示領域
    Rectangle btnRect = ClientRectangle;
    btnRect.X += 2;
    btnRect.Y += 2;
    btnRect.Width -= 4;
    btnRect.Height -= 4;

    Color stColor, edColor;
    if (!pressed)
    {
        stColor = Color.Red;
        edColor = Color.Black;
    }
    else
    {
        // タップされている場合は、色を反転させて描画する
        stColor = Color.Black;
        edColor = Color.Red;
    }

    // 角丸グラデーションボタンの描画
    GraphicsExtension.DrawGradientRoundRectButton(
        g, btnRect, stColor, edColor, Color.Black, FillDirection.TopToBottom);

    // ボタンに表示するテキストの表示(テキストは中央に表示)
    StringFormat sf = new StringFormat();
    sf.LineAlignment = StringAlignment.Center;
    sf.Alignment = StringAlignment.Center;
    g.DrawString(Text, Font, new SolidBrush(Color.White), btnRect, sf);
}

フォーカスが当たっている状態を描画する

フォーカスが当たっている状態を描画します。フォーカスの当たった当たっていないを変化させるのには、OnGotFocusメソッド、OnLostFocusメソッドを利用します。

protected override void OnGotFocus(EventArgs e)
{
    base.OnGotFocus(e);

    // 再描画要求
    Invalidate();
}

protected override void OnLostFocus(EventArgs e)
{
    base.OnLostFocus(e);

    // 再描画要求
    Invalidate();
}

GotFocusイベントが発生すると、FocusedプロパティがTRUEになり、LostFocusイベントが発生するとFocusedプロパティがFALSEになることを利用して再描画要求を行います。

描画更新が行われると、OnPaintメソッドが呼び出されますので、この時にFocusedプロパティの値をDrawButtonメソッドに渡します。

protected override void OnPaint(PaintEventArgs e)
{
    bool pressed = false;
    bool focused = Focused;
    
    DrawButton(e.Graphics, pressed, focused);
}

これでボタンにフォーカスが当たっているのが分かるでしょうか。

画像

ボタンが押されている状態を描画する

次にボタンが押されている状態を描画します。ボタンが押されている押されていないを変化させるには、マウス(画面タップ)とキーボードごとに応じて別々のメソッドを使用します。

マウス(画面タップ)の場合には、OnMouseDownメソッド、OnMouseUpメソッドを利用します。OnMouseDownメソッドは、MouseDownイベントが発生したときに呼び出されます。

protected override void OnMouseDown(MouseEventArgs e)
{
    Capture = true;
    Focus();

    // 再描画要求
    Invalidate();
}

protected override void OnMouseUp(MouseEventArgs e)
{
    Capture = false;

    // 再描画要求
    Invalidate();
}

キーが押された場合は、OnKeyDownメソッド、OnKeyUpメソッドを利用します。ここではEnterキーのみを拾って表示の再描画を行っていますが、好みに合わせて変更してください。対象となったキーが押下されるとCaptureプロパティをTRUEにして、Invalidateメソッドを再描画要求を行います。

protected override void OnKeyDown(KeyEventArgs e)
{
    if (e.KeyCode == Keys.Enter)
    {
        Capture = true;
        Focus();

        // 再描画要求
        Invalidate();
    }
}

protected override void OnKeyUp(KeyEventArgs e)
{
    Capture = false;

    // 再描画要求
    Invalidate();
}

描画更新要求が行われると、OnPaintメソッドが呼び出されます。Captureプロパティの値をDrawButtonメソッドに渡します。

画像

いかがでしょうか? 少し押されているような印象になっていませんでしょうか。これでボタンの描画ができました。

押されたような効果を与えるために、押下時のボタンの淵に陰や光沢をDrawLineなどで入れれば、押されている感が強調され、よりボタンを立体的に見せることができるでしょう。

さいごに

画面上のタップや、キーの押下によって、インタラクティブにボタンの表示が変化したのが分かったでしょうか。

今回までボタンコントロールを、比較的簡単なControlクラスを継承して実装を行いました。これはボタンを描画する処理としての解説をメインとしたかったからです。ボタンコントロールであることを考えると、Buttonクラスを継承して実装するほうがよいかもしれません。

Buttonクラスを継承する場合は、サブクラス化を行う必要があり、本来.NET Compact Frameworkのランタイムが処理してくれる部分を自前でWindows Messageをフックして処理させる等、やや実装が複雑になります。ただ、.NET Compact Frameworkでは外せない技術ですので、次回取り扱いたいと思います。

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

おすすめ記事

記事・ニュース一覧