【C#, WPF】アナログ時計を作る -その4-
こんにちは、しゃげまんじゅです。
前回で基本的に使用においての機能はほぼ完成しました。
今回は時計のサイズが少し大きすぎるように感じたのでサイズを調節できるようにします。
設定画面の作成
まず、スケール変更用の簡易的なダイアログを作成します。
- ① ソリューションエクスプローラーのプロジェクトを右クリックし、
追加→新しい項目を選択 - ② ウィンドウ(WPF)を選択
- ③ 名前を適当なものに変更
(今回は"SettingDialog.xaml"にしました!) - ④ 最後に追加をクリック
作成したSettingDialog.xamlを以下のように編集します。
ButtonのIsDefaultをtrueにすることでEnterでボタンが発動するようになります。
<Window x:Class="AClock.SettingDialog" ~省略~ Title="スケール変更" Height="150 " Width="250"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock Text="スケール変更" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Grid.RowSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14"/> <TextBox x:Name="InputScale" Height="20" Width="35" Grid.Row="0" Grid.Column="2" Grid.RowSpan="2" HorizontalAlignment="Right" VerticalAlignment="Center"/> <TextBlock Text="%" Grid.Column="3" Grid.Row="0" Grid.RowSpan="2" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="14"/> <Button Content="OK" IsDefault="true" Click="ChangeScale" Grid.Column="0" Grid.Row="2" Margin="50,10,10,10" Grid.ColumnSpan="2"/> <Button Content="Cancel" Click="ReturnScale" Grid.Column="2" Grid.Row="2" Margin="10,10,50,10" Grid.ColumnSpan="2"/> </Grid> </Window>
これで、以下のような画面が作成できました。
OKボタン押下時の機能の作成
OKボタンが押された際には入力された数値を親ウィンドウに渡し、画像サイズを計算して変更します。
SettingDialog.xaml.csとMainWindow.xaml.csにそれぞれ以下を追加します。
SettingDialog.xaml.cs
//親ウィンドウ private MainWindow mainWin; //親ウィンドウ受け取り public void setParent(MainWindow win) { mainWin = win; } //変更時 private void ChangeScale(object s, RoutedEventArgs e) { string scaleNum = InputScale.Text; if (int.TryParse(scaleNum, out int i)) { if (i > 0) { //親ウィンドウのsetScale()呼び出し mainWin.setScale(i); this.Close(); } else { //0より大きい値でない MessageBox.Show("0より大きな整数値を入力してください"); } } else { //整数値ではない MessageBox.Show("0より大きな整数値を入力してください"); } }
MainWindow.xaml.cs
//入力値受け取り public void setScale(int i) { ChangeScale(base_i, i); ChangeScale(hour_i, i); ChangeScale(minute_i, i); ChangeScale(second_i, i); } //画像サイズ設定 private void ChangeScale(Image img, int i) { img.Width = img.Width * (double)i / 100.0; img.Height = img.Height * (double)i / 100.0; }
キャンセルボタン押下時の機能の作成
キャンセルボタンを押した際には何もしないのでウィンドウを閉じる処理だけですね。
//キャンセル時 private void ReturnScale(object s, RoutedEventArgs e) { this.Close(); }
右クリックメニューへの登録
作成した設定画面を呼び出せるように右クリックメニューを編集します。
MainWindow.xamlの<ContextMenu>内に以下の1行を追加します。
<MenuItem Header="スケール変更" Click="Button_Click_rescale"/>
加えて、MainWindow.xaml.csに以下を追加します。
setParent()を呼び出して親ウィンドウを登録することで、ダイアログ側からMainWindow.xaml.csのsetScale()を呼び出せるようになります。
private void Button_Click_rescale(object s, RoutedEventArgs e) { var diawin = new SettingDialog(); diawin.Owner = GetWindow(this); diawin.setParent(this); diawin.ShowDialog(); }
以上でアナログ時計が完成しました。
ここまでお読みいただきありがとうございました。
自分で作るとデザインも好きに変更できるので良ければ作ってみてください!
【C#, WPF】アナログ時計を作る -その3-
こんにちは、しゃげまんじゅです。
前回で時計機能は完成しましたが、タイトルバーの無いスタイルを使うとウィンドウの移動・終了などの機能がデフォルトで付いておらず不便なので追加していきます。
ウィンドウサイズの設定
前回ウィンドウのHeight・Widthを削除したのでウィンドウサイズが画像にフィットしていません。
以下の一行を追加することによってウィンドウサイズが自動的に画像にフィットするようにします。
//コンテンツに合わせて自動的にサイズを設定 this.SizeToContent = SizeToContent.WidthAndHeight;
ウィンドウの移動
MainWindow()内に以下の一行を追加します。
これでドラッグによりウィンドウを動かせるようになりました。
//ドラッグで動かせるようにする MouseLeftButtonDown += (o, e) => DragMove();
ウィンドウの終了
右クリックでメニューが出るようにMainWindow.xamlに記述します。
<Window.ContextMenu> <ContextMenu> <MenuItem Header="終了" Click="Button_Click_exit"/> </ContextMenu> </Window.ContextMenu>
追加したメニューをクリックした際の処理をMainWindow.xaml.csに記述します。
これでメニューから終了操作ができるようになりました。
private void Button_Click_exit(object s, RoutedEventArgs e) { Application.Current.Shutdown(); }
ウィンドウを最前面に固定
MainWindow.xaml内に先ほど追加した<ContextMenu>に以下の一行を追加します。
<MenuItem Header="最前面に固定" IsChecked="False" IsCheckable="True" Checked="fixedFront_Checked" Unchecked="fixedFront_Unchecked"/>
MainWindow.xaml.csにチェック時・未チェック時の処理を記述します。
これでチェック時に常に最前面に表示されるようになりました。
//最前面に固定 //チェック時 private void fixedFront_Checked(object s, RoutedEventArgs e) { this.Topmost = true; } //未チェック時 private void fixedFront_Unchecked(object s, RoutedEventArgs e) { this.Topmost = false; }
次回は画像のサイズを変更できるように設定します。
次回更新日:2021/05/14 19:30
【C#, WPF】アナログ時計を作る -その2-
こんにちは、しゃげまんじゅです。
前回に引き続き、アナログ時計を作っていきます。
レイアウトの作成
まず、XAMLを編集して前回作成した画像を貼り付けます。
1. 画像の取り込み
このままでは画像を使用できないので、準備をします。
- ① ソリューションエクスプローラーのプロジェクトを右クリックし、
プロパティを選択 - ② 表示されたプロパティのリソースタブを選択
- ③ 中央の「…ファイルを作成する…」と書かれた文字列をクリック
- ④ 使用する画像をドラッグ&ドロップ
- (以下、それぞれの画像に対して)
- ⑤ ソリューションエクスプローラーの画像ファイルを右クリックし、
プロパティを選択 - ⑥ ビルドアクションをリソースに変更 (ここ重要!)
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】アナログ時計を作る -その1-
個人的にデスクトップ上にアナログ時計が欲しかったので作ってみました。
完成図
画像の用意
まず、使用する画像を用意します。
使用する画像は以下の4つ!
- 時計盤
- 短針
- 長針
- 秒針
今回使用した画像です
時計盤
|
短針
|
長針
|
秒針
|
プロジェクトの作成
Visual Studio 2019で作っていきます。
~以下の順番で作成~
- 新しいプロジェクトの作成
- WPFアプリケーション
- プロジェクト名&ソリューション名の設定
- .NET Core 3.1
次回は実際にコーディングしていきます。
まあ、画像さえ用意できれば完成したも同然ですね☆