しゃげログ

プログラミング、ときどき旅行

【C#, WPF】アナログ時計を作る -その2-

こんにちは、しゃげまんじゅです。

前回に引き続き、アナログ時計を作っていきます。

 


 

レイアウトの作成

まず、XAMLを編集して前回作成した画像を貼り付けます。

1. 画像の取り込み

このままでは画像を使用できないので、準備をします。

  1. ① ソリューションエクスプローラーのプロジェクトを右クリックし、
    プロパティを選択
  2. ② 表示されたプロパティのリソースタブを選択
  3. ③ 中央の「…ファイルを作成する…」と書かれた文字列をクリック
  4. ④ 使用する画像をドラッグ&ドロップ
  5. (以下、それぞれの画像に対して)
  6. ⑤ ソリューションエクスプローラーの画像ファイルを右クリックし、
    プロパティを選択
  7. ⑥ ビルドアクションをリソースに変更 (ここ重要!)

f:id:huyuki_inari:20210508221522p:plain

f:id:huyuki_inari:20210508230845p:plain

 

2. XAMLの編集

MainWindow.xamlを編集します。

タイトルバーは邪魔なので、AllowsTransparency, WindowStyle, Backgroundの3項目を追加・編集します。
ついでに、HeightとWidthの項目は特に必要ないので削除します。

<Window x:Class="AClock.MainWindow"
        ~省略~
        Title="MainWindow" AllowsTransparency="True" WindowStyle="None" Background="Transparent">

 

先ほど取り込んだ画像を配置していきます。

HorizontalAlignment・VerticalAlignmentはCenter、x:Nameは好きな名前でOKです。
Width・Heightは同じ値にしておきます。
※針の画像は回転させるので時計盤の画像からはみ出さないサイズに設定しています。

<Grid>
        <!--(針の画像の対角線の長さ)=(時計盤の画像の1辺の長さ)-->
        <!--時計盤-->
        <Image x:Name="base_i" Source="Resources/AClock_0.png" HorizontalAlignment="Center" VerticalAlignment="Center" Width="400" Height="400"/>
        <!--短針-->
        <Image x:Name="hour_i" Source="Resources/AClock1-2_45.png" HorizontalAlignment="Center" VerticalAlignment="Center" Width="282" Height="282"/>
        <!--長針-->
        <Image x:Name="minute_i" Source="Resources/AClock1-1_45.png" HorizontalAlignment="Center" VerticalAlignment="Center" Width="282" Height="282"/>
        <!--秒針-->
        <Image x:Name="second_i" Source="Resources/AClock1-3_45.png" HorizontalAlignment="Center" VerticalAlignment="Center" Width="282" Height="282"/>
</Grid>

 

時計機能の作成

MainWindow.xaml.csを編集して、時計として最低限動くようにしていきます。

DispatcherTimerのIntervalを100ミリ秒に設定し、この間隔でTickイベントを呼び出します。
Tickイベントでは、針の角度をそれぞれ計算し、LayoutTransformを利用して画像を回転させています。
(針の画像は45°回転しているので計算時に引くように注意です!)

最後にMainWindow()でタイマーを生成し、起動させます。
また、終了時処理として一応タイマーが停止するようにしておきましょう。

~省略~
//タイマー用
using System.Windows.Threading;

namespace AClock
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        private DispatcherTimer timer;

        public MainWindow()
        {
            InitializeComponent();

            //タイマー生成
            timer = CreateTimer();
            //タイマー起動
            timer.Start();
            //終了時処理
            this.Closing += (s, e) => timer.Stop();
        }

        //タイマー
        private DispatcherTimer CreateTimer()
        {
            var dtimer = new DispatcherTimer(DispatcherPriority.SystemIdle);
            //タイマーイベント発生間隔設定
            dtimer.Interval = TimeSpan.FromMilliseconds(100);
            //タイマーイベント発生時処理
            dtimer.Tick += (sender, e) =>
            {
                //現在時刻取得
                var currentTime = DateTime.Now;
                //針の角度を計算・代入
                int h_angle = (currentTime.Hour % 12) * 30 + currentTime.Minute * 30 / 60 - 45;
                int m_angle = currentTime.Minute * 360 / 60 - 45;
                int s_angle = currentTime.Second * 360 / 60 - 45;

                //LayoutTransformを利用して針を回転させる
                hour_i.LayoutTransform = returnTransform(h_angle);
                minute_i.LayoutTransform = returnTransform(m_angle);
                second_i.LayoutTransform = returnTransform(s_angle);
            };

            return dtimer;
        }

        //RotateTransformのAngle設定
        private RotateTransform returnTransform(int angle)
        {
            RotateTransform transform = new RotateTransform { Angle = angle };
            return transform;
        }

    }
}

 


今回で時計としては最低限使用できるようになりました!
次回は細かい部分の設定をしていきます。

次回:【C#, WPF】アナログ時計を作る -その3-