宇宙仮面の
C# Programming

 
Image

Click Once / アナログクロックを作る

開発環境: Visual Studio 2005 

1.目次

2.目的

次のようなアナログクロックの Click Once アプリケーションを作る。

Image

次のURLから試してください。
http://uchukamen.com/ClickOnce/AnalogClock/publish.htm

3.参考書

(1) Using NASA Imagery and Linking to NASA Web Sites

4.アナログクロックの作り方

1. メニュー→ファイル→新規作成→プロジェクト
で新しいプロジェクトのダイアログで、プロジェクト名を AnalogClock とする。名前は任意。
Image


2. PictureBoxはダブルバッファリングにより高速な描画機能を持っています。直接 Form1 へ描画することも可能ですが、PictureBox を使用するほうが、より柔軟に画像を扱うことができ、高速に処理ができます。そこで、今回は PictureBox に画像を描画し、その上にアナログ時計を描画するように作ります。そのために、まずツールボックスから PictureBox を Form1 へドラッグアンドドロップします。PictureBox の右上に小さなアイコンがあるので、それをクリックすると、PictureBox タスクが表示されます。ここで、「親コンテナにドッキングする」を選択し、PictureBox がForm1を覆うようにします。

Image

3. 次に、1秒ごとに時計を動かす必要があります。このために、ツールボックスから Timer をForm1 へドラッグアンドドロップします。
Image

4. Timer のプロパティ で Interval を 1000 (1秒)、Enabled を True とし、1秒ごとにタイマーによりキックがかかるようにします。
Image

5. タイマーをダブルクリックすると、次のように timer1_Tick イベントが自動的に追加される。この timer1_Tick は1秒に1回呼び出されることになります。そこで、pictureBox1.Invalidate() を呼び出すことにより、1秒ごとに pictureBox1 を無効化します。すると、自動的に pictureBox1 の OnPaint が呼ばれるようになります。そこで、pictureBox1 のプロパティを表示し、稲妻ボタンをクリックします。この中で、Paint イベントをダブルクリックすると、picture1_Paint イベントが追加されます。

Image

そこで、時計を書くためのメソッド DrawClock( e.Graphics ) を呼び出します。

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

namespace AnalogClock
{
   
public partial class Form1 : Form
   
{
       
public Form1()
        {
            InitializeComponent();
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            DrawClock(e.Graphics);
        }
    }
}

6. それでは、実際に時計を描画するための DrawClock を実装しましょう。
処理を簡単にするために、
Graphicsの原点を pictureBox1 の中心に移動(Translate) して描画しています。そのことだけ注意すれば、DrawClock 自体は難しくないので、コードを読めば理解できると思います。

7. あとは適当な画像を pictureBox1 の image プロパティにセットします。
VS 2005 では、ローカルとプロジェクトの2つのリソーススコープをサポートしています。

ローカルリソース・・・フォームまたはローカルリソースファイルで指定します。
プロジェクトリソース・・・プロジェクトのリソースファイルで指定します。

今回は、特にリソースファイルを後から操作することはしないので、どちらでもOKです。

ローカルリソースのインポートボタンより適当な画像をインポートします。ここでは、NASAからファイルをダウンロードしたものを使用します。
Image

8. ここまでで実行すると、次のようなアプリケーションが起動できるはずです。
Image

9. このままでは、画像のサイズとアプリケーションのサイズが一致しません。そこで、画像のサイズにアプリケーションのサイズを合わせます。Form1 の Load イベントをダブルクリックして、イベントハンドラを追加します。

Image

ここで、pictureBox1 の Image の Width, Height で、Form1 の ClientSizeCore を合わせます。

private void Form1_Load(object sender, EventArgs e)
{
    SetClientSizeCore(pictureBox1.Image.Width, pictureBox1.Image.Height);
}

あとは、フォームをリサイズできないように、フォームの FormBorderStyle をFixed3Dにします。

 

5.アナログクロックのソースコード

 
AnalogClock.cs
using System;
using
System.Collections.Generic;
using System.ComponentModel;
using System.Data;using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace AnalogClock
{
    public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private void timer1_Tick(object sender, EventArgs e)
            {
                pictureBox1.Invalidate();
            }
            private void DrawClock(Graphics g)
            {
                g.TranslateTransform(pictureBox1.Width / 2, pictureBox1.Height / 2, MatrixOrder.Append);
                Point center = new Point(0, 0);
                DateTime time = DateTime.Now;
                double secAng = 2.0 * Math.PI * time.Second / 60.0;
                double minAng = 2.0 * Math.PI * (time.Minute + time.Second / 60.0) / 60.0;
                double hourAng = 2.0 * Math.PI * (time.Hour + time.Minute / 60.0) / 12.0;
                int r = Math.Min(ClientSize.Width, ClientSize.Height) / 2;
                int secHandLength = (int)(0.9 * r);
                int minHandLength = (int)(0.7 * r);
                int hourHandLength = (int)(0.5 * r);
                Point secHand = new Point((int)(secHandLength * Math.Sin(secAng)),
                (int)(-secHandLength * Math.Cos(secAng)));
                Point minHand = new Point((int)(minHandLength * Math.Sin(minAng)),
                (int)(-minHandLength * Math.Cos(minAng)));
                Point hourHand = new Point((int)(hourHandLength * Math.Sin(hourAng)),
                (int)(-hourHandLength * Math.Cos(hourAng)));
                using (Pen BluePen = new Pen(Color.Blue, 3))
                    g.DrawLine(BluePen, center, secHand);
                using (Pen GreenPen = new Pen(Color.Green, 5))
                    g.DrawLine(GreenPen, center, minHand);
                using (Pen RedPen = new Pen(Color.Red, 7))
                    g.DrawLine(RedPen, center, hourHand);
            }
            private void FitToBackgroundImage()
            {
                this.SetClientSizeCore(this.BackgroundImage.Width, this.BackgroundImage.Height);
            }
            private void pictureBox1_Paint(object sender, PaintEventArgs e)
            {
                DrawClock(e.Graphics);
            }
            private void Form1_Load(object sender, EventArgs e)
            {
                SetClientSizeCore(pictureBox1.Image.Width, pictureBox1.Image.Height);
            }
    }
}
 

なお、この程度のアプリケーションでは、using パターンを必ずしも使う必要はありません。詳しくは、http://uchukamen.com/Programming/GC/index.htm#GCお任せパターン を参照してください。

6.Click Once

 
メニュー→ビルド→AnalogClock の発行を選択しますすると発行ウィザードが起動しますので、発行する場所を指定します。 発行する場所は、ASP.NET 2.0 がサポートされている環境である必要があります。
Image

次に、オフラインでも利用できますか?と聞いてきます。
オフラインでも利用する場合には、クライアント側にインストールされます。
ここでは、大したソフトでもないので、毎回ネットから実行するようにします。
ユーザ名、パスワードを聞いてきますから、適切な入力を行います。

Image

すると、確認画面が表示されますので、完了ボタンを押します。

Image

7.クリックワンスの実行

すると、次のようなウェブブラウザが起動します。

Image

実行ボタンを押すと、

Image

ちゃんとした発行元の証明がないため、という画面が表示されます。

また、.NET Framework 2.0 がインストールされていないと、次のようなセットアップを問い合わせるダイアログが表示されます。

Image

ここで実行をクリックすると、次のように Click Once でアプリケーションが起動します。
Image

試してみたい人は、次のURLをクリックしてみてください。

http://uchukamen.com/ClickOnce/AnalogClock/publish.htm