C# Programming

Image

簡単な C# モバイルアプリケーション開発2
デジタルクロック

開発環境: Visual Studio 2005 

1.目次

1.目次
2.目的
3.参考書
4.作り方
5.ダウンロード
6.ソースコード
7.さいごに

2.目的

W-Zero3 用のWindows Mobile の簡単なアプリケーションとして、デジタルクロックを作成します。

Image

ここでは ImageList によって、簡単に見栄えの良いアプリケーションができることを説明するとともに、Windows Mobileでの開発で注意すべきことを説明したいと思います。

3.参考書

  1. C#研究室.Live Space / W-ZERO3
  2. MSDN .NET Compact Framework 向けの表示方向切り替え対応および高dpi対応アプリケーションの開発
  3. WZero3StatusMeter

4.作り方

 

4.1 基本的な機能やデザインを決める

簡単なデジタルクロックであれば、Label で文字を書いてあげればよいわけで、なにも悩む必要はありません。しかし、搭載フォントの種類が限られており、あまりパッとした感じにはなりません。そこで、たとえば7セグメントLEDで少し見た目を良くしたいという場合には、次の2つの方法が考えられます。

  1. 7セグメントLEDをGDI+の線やポリゴン(ベクターグラフィックス)で描画する方法
  2. 画像で表示する方法

それぞれ、長所短所があります。まず、GDI+で描画する方法ですが、ベクターグラフィックスで描画することになるので、大きさに依存せずにきれいに描画できます。しかし、グラフィックス描画を実装する必要があり、多少面倒です。GDI+の勉強にはちょうどいいと思いますが、サクサクっと作りたい場合には、不向きです。

画像で表示する方法は、画像を貼り付けていけばよいので、非常に簡単にできます。しかし、注意しなければならないのが、画像のサイズです。あまり小さい画像を引き延ばして使うと、ぎざぎざしてしまいます。逆に大きいと、きれいに表示はできますが、メモリを食いつぶしてしまいます。

W-Zero3のような Windows Mobileデバイスでは、最大サイズが640x480ですから、画面サイズが限られることと、Windows のようにウィンドウのリサイズは行いませんので、割り切って画像サイズを固定することができます。

以上より、画像で表示する方法のほうが、簡単です。ここではデジタルクロックの数字を、画像を使って表示する方法を説明します。

4.2 画像パーツの作成

まず、画面パーツを作成します。私の場合、高価なデザインツールなど持っていないので、PowerPointで代用しました。お手軽に作る分にはそれなりに使えます。次のように、 7セグメントLEDのデザインで、0−9をPowerPointで描画し、スクリーンショットを取り、画像ファイルに落とします。

Image

そのファイルをペイントなどのソフトで、数字ごとの画像に分割します。今回必要な画像のパーツは 0−9と、”:”の11個だけです。

Image

ここで注意しなければならないのが、画像のサイズです。PPTで作った画像をどのサイズにするのか、実際の画面サイズに合わせて、大きさを決定します。大きすぎると、アプリケーションのサイズが大きくなります。小さすぎると、ぎざぎざしてしまいます。また、場合によっては解像度の違いによりモアレが発生してしまう場合もあるでしょう。できれば、表示サイズと実際のデザインのサイズが一致しているのが望ましいです。

4.3 プロジェクトの作成

  1. プロジェクトの新規作成
    Visual StudioImageのメニューからプロジェクトの新規作成で、プロジェクトの種類で [スマートデバイス] → [デバイスアプリケーション] を選択します。
     
  2. ターゲットデバイスの設定
    エミュレータでも可能ですが、エミュレータではレスポンスが悪く、かったるいです。そこで、Windows Mobile 5.0 Pocket PC Deviceを指定して、実機上で開発します。
     
  3. Formの [FormFactor]プロパティ
    [Windows Mobile 5.0 Pocket PC VGA] を指定します。
     
  4. 画像を追加する。
    次のように、ソリューションエクスプローラに画像をドラッグアンドドロップで追加します。このとき、画像用のフォルダーを作成しておくとよいでしょう。
    Image
     

4.4 実装

実装は至って簡単です。タイマーを使って、1秒ごとに、時間を描画すればよいだけです。

  1. PictureBoxの貼り付け
    背景画像を張り付けるために、Picture をFormに貼り付けます。Dockプロパティは Fill とします。 画像を"Image"プロパティに貼り付けるか、"BackColor"プロパティで好きな色にしてください。ここでは、"BackColor"プロパティをBlackにします。
     
  2. タイマーの追加
    1秒ごとに時計を更新するために、タイマーを追加します。タイマーの Interval プロパティは 1000(1秒)とします。 また、フォームがアクティブでない場合に、処理を行う必要はないので、フォームがアクティブになった場合に、タイマーをイネーブルにし、フォーム がアクティブではなくなった場合に、タイマーをオフにします。このために、フォームの"Activated"、"Deactivated"イベントハンドラーを 追加し、次のように実装します。

    private void Form1_Activated(object sender, EventArgs e)
    {
        timer1.Enabled =
    true;
    }

    private void Form1_Deactivate(object sender, EventArgs e)
    {
        timer1.Enabled =
    false;
    }
     

  3. タイマーのイベントハンドラーを追加
    タイマーにイベントハンドラーを追加します。ハンドラーの処理では、時計を描画する処理(DrawClock)を呼び出します。

    private void timer1_Tick(object sender, EventArgs e)
    {
        DrawClock();
    }
     

  4. 7セグメントで、時間、分、秒と、”:” を表示するためのPictureBoxを貼り付ける
    12:34:56のように表示します。そこで、それぞれに1つのPictureBoxを貼り付けます。
    Image
    PictureBoxの名前は、わかりやすいように、たとえば、次のようにします。
    pictureBoxH10
    pictureBoxH1
    pictureBoxColon1
    pictureBoxM10
    pictureBoxM1
    pictureBoxColon2
    pictureBoxS10
    pictureBoxS1
     
  5. pictureBoxH10〜pictureBoxS1のImageプロパティに"0"の画像を貼り付けます。pictureBoxColon1, pictureBoxColon2にコロンの画像を貼り付け、SizuModeプロパティを StretchImageにします。これで次のような表示なると思います。この段階で画像の位置、サイズなどを調整します。

    Image
     
  6. 次に、ImageListを貼り付けます。ImageListのImagesプロパティをクリックすると、次のように"..."ボタンが表示されますので、これをクリックします。このとき、ImageSizeは、上記pictureBoxのサイズと同じにします。
    Image
     
  7. すると、次のようなImageCollection コレクションエディタが表示されますので、画像の 0〜9を順番に貼り付けます。
    Image
     
  8. 時刻の表示
    現在の時刻を取得し、それを時間(10の位、1の位)、分(10の位、1の位)、秒(10の位、1の位)を計算します。その各桁の数字をもとに、SetClock(...) で画像を割り当ててあげます。

    private void DrawClock()
    {
       
    DateTime dt = System.DateTime.Now;

       
    int h10 = dt.Hour / 10;
       
    int h1 = dt.Hour % 10;
       
    int m10 = dt.Minute / 10;
       
    int m1 = dt.Minute % 10;
       
    int s10 = dt.Second / 10;
       
    int s1 = dt.Second % 10;

        SetClock(h10, h1, m10, m1, s10, s1);
    }


    private
    void SetClock(int h10, int h1, int m10, int m1, int s10, int s1)
    {
        pictureBoxH10.Image.Dispose();
        pictureBoxH1.Image.Dispose();
        pictureBoxM10.Image.Dispose();
        pictureBoxM1.Image.Dispose();
        pictureBoxS10.Image.Dispose();
        pictureBoxS1.Image.Dispose();

        pictureBoxH10.Image = imageList1.Images[h10];
        pictureBoxH1.Image = imageList1.Images[h1];
        pictureBoxM10.Image = imageList1.Images[m10];
        pictureBoxM1.Image = imageList1.Images[m1];
        pictureBoxS10.Image = imageList1.Images[s10];
        pictureBoxS1.Image = imageList1.Images[s1];
    }

    注意1
    pictureBoxのDispose()を呼んでいますが、これを呼ばないと OutOfMemoryExceptionで落ちます。Windows Mobileだと、さすがに明示的に画像を廃棄してあげないと、メモリがガベージコレクションで解放される前に、メモリを使い切って、落ちてしまいます。画像を使うと楽なのですが、メモリの消費状況には十分注意してください。

    注意2
    ステップ5のところで、"0"の画像を張り付けておかないと Dispose() でNullReferenceExceptionで落ちます。ここでは、画像を貼り付けておくことを前提とした実装にして、エラー処理を省いています。

     
  9. 動作の確認
    ここまでで、実行してみてください。時刻が表示されればOKです。

    Image

    ここまで見ていただければお分かりのように、20行ちょっとで実現できます。ここまで、画像の作成を除いて、30分ぐらいで完成です。ImageListを使うと簡単でしょ?

ここでは、実装しても20行程度のコードなので Form に直接コントロールを貼り付けましたが、このデジタルクロック部分をユーザーコントロールにしてしまえばほかでも使いまわしできますし、コード自体もすっきりします。ユーザーコントロールは、”外気温計〜現在の場所、現在の時間の気温を表示”の例を見てください。

4.5 残りの作業

次に、お決まりの次の作業を行えば、完成です。詳細は、参考文献(2)、(3)を参照してください。

  1. 縦型、横型レイアウトの調整
  2. メインメニューの実装
  3. アイコンの追加
  4. バージョン情報の表示
  5. インストーラの追加

5. ダウンロード

Version 1.0.0.0  2007/3/31 WZero3Clock.CAB

6. ソースコード

メイン部分のソースコードです。

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Uchukamen.WZero3
{    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void menuItemTerminate_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void menuItem2_Click(object sender, EventArgs e)
        {
            FormAbout formAbout = new FormAbout();
            formAbout.ShowDialog();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            DrawClock();
        }

        private void DrawClock()
        {
            DateTime dt = System.DateTime.Now;

            int h10 = dt.Hour / 10;
            int h1 = dt.Hour % 10;
            int m10 = dt.Minute / 10;
            int m1 = dt.Minute % 10;
            int s10 = dt.Second / 10;
            int s1 = dt.Second % 10;

            SetClock(h10, h1, m10, m1, s10, s1);
        }

        private void SetClock(int h10, int h1, int m10, int m1, int s10, int s1)
        {
            pictureBoxH10.Image.Dispose();
            pictureBoxH1.Image.Dispose();
            pictureBoxM10.Image.Dispose();
            pictureBoxM1.Image.Dispose();
            pictureBoxS10.Image.Dispose();
            pictureBoxS1.Image.Dispose();

            pictureBoxH10.Image = imageList1.Images[h10];
            pictureBoxH1.Image = imageList1.Images[h1];
            pictureBoxM10.Image = imageList1.Images[m10];
            pictureBoxM1.Image = imageList1.Images[m1];
            pictureBoxS10.Image = imageList1.Images[s10];
            pictureBoxS1.Image = imageList1.Images[s1];
        }

        private void Form1_Activated(object sender, EventArgs e)
        {
            timer1.Enabled = true;
        }

        private void Form1_Deactivate(object sender, EventArgs e)
        {
            timer1.Enabled = false;
        }
    }
}

 

7. さいごに

簡単なモバイルアプリケーション開発2に続いて、簡単なモバイルアプリケーション開発3を見てくださいい。ここでは、電源の監視を行います。これにより、W-Zero3の電源状態を監視して、バッテリーに切り替わってからの時間をカウントダウンするという組み合わせ技もできるようになります。