C# で MyClock Ver 0.10 を作る (1/2)
プログラム電卓のためのC#プログラミング
2017/01/31
初めて作る C# プログラム - MyClock
仕 様
- フォントが大きい
- 時計は半透明で常に前画面表示
▍MyClock プロジェクトを作る
初めての C# なので、分かる範囲で手順とポイントを記録しておきます。
1. Visual Studio Community 2015 を起動
起動時に、管理者権限にするかそうでないかの選択肢があります。取り敢えず管理者権限で起動します。
2. 初めてのソリューションとプロジェクトの作成
▶ 新しいプロジェクト作成の方法
新しいプロジェクト作成には複数の方法があります。
- スタートページにある「新しいプロジェクト ...」のリンクをクリック
- ツールバーの左から3詰めの"新しいプロジェクト"ボタンをクリック
- メニューで、[ファイル] - [新規作成] - [プロジェクト] を選ぶ
▶ ひな形プロジェクトを選ぶ。
[テンプレート] - [Visual C#] - [Windows] から「Windowsフォームアプリケーション」を選択
「名前(N):」と「ソリューション(M):」に MyClock と入力し、「場所(L):」に適切に入力します。
なお、「場所(L):」で設定したフォルダの下に、ソリューションに指定した名前のフォルダが自動的に作られ、その下に必要なファイルが自動生成されます。
バージョン管理を分かり易くするために、新規プロジェクトを作る前に MyClockフォルダを作っておき、さらにその下に例えば MyClock0100 とバージョンが分かるフォルダも作っておき、このフォルダを「場所(L):」に指定しています。
<MyClock>
<MyClock0100> ← [場所(L):」に入力したフォルダ
[OK] をクリックすると、ひな形のプロジェクトが作成されます。自動作成だけで合計 92KB のファイルが数多く生成されます。
<MyClock>
<MyClock0100> ← [場所(L):」に入力したフォルダ
<MyClock>
MyClock.sln
<vs.>
<MyClock>
App.config
MyClock.csproj
Form1.cs
Form1Designer.cs
Program.cs
<bin>
<Debug>
MyClock.exe.config
MyClock.vshost.exe
MyClock.vshost.exe.config
MyClock.vshost.exe.manifest
<obj>
<Debug>
MyClock.csproj.FileListAbsolute.txt
DesignTimeResolveAssemblyReference.cache
TemporaryGeneratedFile_xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx.cs
TemporaryGeneratedFile_yyyyyyyy_yyyy_yyyy_yyyy_yyyyyyyyyyyy.cs
TemporaryGeneratedFile_zzzzzzzz_zzzz_zzzz_zzzz_zzzzzzzzzzzz.cs
<TempPE>
<Properties>
AssemblyIngo.cs
Resource.Designer.cs
Resource.resx
Setttings.Designer.cs
Settings.settings
そして、フォームデザイナーが開いて、デフォルトの (素の) フォームが現れます。

▶ 初めてビルドしてみる
メニューバーの下に「Debug」「Any CPU」とあります。この状態で、メニューで、[ビルド(B)] - [ソリューションのビルド] を選び、ビルドを実行します。すると、出力ウィンドウで
1>------ ビルド開始: プロジェクト:MyClock, 構成:Debug Any CPU ------
と表示され、その後すぐに
1>------ ビルド開始: プロジェクト:MyCloxk, 構成:Debug Any CPU ------
1> MyClock -> C:\MyData\MySource\VS2015\Projects\C#\MyClock\MyClock0100\MyClock\MyClock\bin\Debug\MyClock.exe
と1行追加表示されます。デバッグモードでビルドした実行ファイル名とパスが表示されます。
ここで、
1> MyClock -> C:\MyData\MySource\VS2015\Projects\C#\MyClock\MyClock0100\
は「場所(L):」で設定したパスで、
その下の MyClock フォルダがソリューション MyClock のフォルダ、
さらにその下にある 同じ名前の MyClock フォルダが プロジェクト MyClock のフォルダです。
そして、実行ファイル MyClock.exe は プロジェクトフォルダの下の bin\Debug フォルダに作成されていることが分かります。リリースモードでビルドすると、bin\Release フォルダ内にファイルが出力されます。
ビルドが終わると、出力は以下のようになります。
1>------ ビルド開始: プロジェクト:MyCloxk, 構成:Debug Any CPU ------
1> MyClock -> C:\MyData\MySource\VS2015\Projects\C#\MyClock\MyClock0100\MyClock\MyClock\bin\Debug\MyCloxk.exe
========== ビルド: 1 正常終了、0 失敗、0 更新不要、0 スキップ ==========
1 正常終了 となっているのでビルドエラーが無かったことが分かります。
▶ デバッグモードで実行してみる
方法は複数あります。
- [F5]キーを押す
- ツールバーの[▶ 開始]ボタンを押す
- メニューで、[デバッグ] - [デバッグの開始] を選ぶ

素のウィンドウが既にできています。最小化ボタン、最大化ボタン、中止ボタン、システムメニューを出すアイコン、プログラムのタイトル Form1 が備わっていて、いっちょ前にウィンドウの陰までできています。これは Windows 10 で実行した時の画像です。Windows 7 や 8 ではその環境でのデフォルトのウィンドウになる筈です。
1行もコードを書かずに、取り敢えずここまでは自動的に作ってくれますが、昔の VC++ 6 でも変わりなく驚くことでもありません。実はVisual Studio 2015 での開発の段取りは、基本は以前の Visual Studio 6 と同じような感じですので、経験があれば必要なものは探して使えると思います。
ここで、MyClock ソリューションと、その中に含まれる MyClock プロジェクトが作成されたことになります。このソリューションの中に 新しいプロジェクトを作って含めることができます。
▶ namespace、class そして Form
私には Namespace (名前空間) は新しい概念で、クラスやメンバー は MFC (Microsoft Foundation Class) で馴染みがあり、Form は Visual Basic で出てきました。
C# は、これらが混じった感じですね。C++ で記述できる Visual Basic とでも言えそうな感じです。
画面右にあるソリューションエクスプローラで、Form1.cs を右クリックして [コードの表示] を選んで、自動作成されたコードを眺めてみます。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MyClock // これがプロジェクトMyClock
{
public partial class Form1 : Form // ここで Form1 ウィンドウに必要な処理を書く
{
public Form1() // Form1 の最初の処理として初期化している
{
InitializeComponent();
}
}
}
ここで、using は、VC++ の include のような感じで、予め準備されているライブラリからデフォルトで必要なものが列挙されていて、今後必要に応じて追加することになります。
public Form()
{
}
は、この先頭の位置に記述しておかないと、開発環境がエラーを出します(実際悩みました)。Form1 のインスタンス生成で最初の1回だけ行われる処理のようです。
さらに分かることとしては、
using System.Windows.Forms;
で、関連づけられた Forms に 基底クラスの Form の定義があって、それをサブクラス化して Form1 クラスが作られています。
仮に、以下のように class Form1 の中で、public な静的文字列変数 m_variable を宣言しておきます。
namespace MyClock
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public static string m_variable; // 静的文字列変数
}
}
この変数へ、class Form1 の外の例えば class Form2 からアクセスするには、
Form2 の中では、
(namespace).(class).m_variable
つまり
Form1.Form1.m_variable
と記述する必要があります。スコープを考えると名前空間がクラスの上位にあるわけです。
そして、Form2 の中で、一例として
public string m_var = Form1.Form1.m_variable;
と橋渡しをしておけば、タイプ数の少ない m_var を使えて便利です。
なお、Visual Studio では正しく記述すれば、クラス名を Form1 と色分けして表示してくれるので、目安になって便利です。
▶ Form名 = クラス名
今、名前空間とプロジェクト名が、MyClock になっています。フォーム名とクラス名は自動生成された Form1 のままです。
これを適切な名前に変更します。時間を表示させるので、Display としましょう。フォーム名とクラス名を変更するために、全て手で変更するのは大変なので、自動変更の機能を使います。但しプログラムが込み入ってくると自動生成も完璧ではないと心配される (どこまで信用して良いか分からない)ので、自動生成された直後に名称変更を自動で行わせることにします。
ちょっと脱線しますが、ここで自動作成された主なファイルは、以下です。
- Form1.cs
- Form1.Designer.cs
- Program.cs
Form1.Designer.cs は開発環境の機能を使って自動でコードに落としてくれるものです。部品をフォームへドラッグ&ドロップで追加したり、フォームや部品のプロパティを変更したり、イベントハンドラのテンプレート作成などがコーディングせずに行えます。そして、その結果がこのファイルと Form1.cs の両方に反映されます。
Form1.Designer.cs は宣言や定義が書き込まれ、Form1.cs にはテンプレートが書き込まれます。このテンプレートの中に具体的にコーディングしてアプリを作ってゆきます。
一旦作成したイベントハンドラが不要になった場合は、Form1.cs と Form1.Designer.cs の両方で関連する部分だけを慎重に削除しないと、Visual Studio が混乱して面倒なことになります。
Program.cs には WinMain() 関数が書かれていてます。これはアプリが起動した時に最初に実行されるもので、終了時にもここへ戻ってきて必要な処理を行います。アプリが起動してからフォームのインスタンスを生成する前に必要な処理はここにコーディングします。
話を元に戻して、フォーム名とクラス名を実際に Display に変更します。
ソリューションエクスプローラで、Form1.cs で右クリックして[名前の変更] を選ぶと、Form1.cs が反転するので、そこで Display.cs となるように変更します。すると以下のメッセージボックスが現れます。

ここで [はい]をクリックすると、自動で名称変更してくれます。他の関連ファイル名も変更され、主要ファイル名は以下のようになりました。
- Display.cs
- Display.Designer.cs
- Program.cs
上記以外のファイル名も変更されているのは、ソリューションエクスプローラで確認できます。

Display.cs [デザイン] で表示されるフォームのタイトルバーは、まだ Form1 となっています。これはフォーム名やクラス名とも無関係で、単にフォームのテキスト (Display.Text) の設定が Form1 のままになっているためです。これは、フォームのプロパティで変更できます。プログラム中で変更するには Text プロパティを使って、
Display.Text = "変更する文字列";
とします。タイトルバーに表示するテキストをアプリの状況に応じて動的に変更したい時に使えます。
今回は、フォームのテキストを Form1 から MyClock に変更してみます。Display.cs[デザイン]を表示して、フォームをクリックすると、Displayフォームのプロパティ一覧が(右下に)表示されるので、そこで Text というキーを探して、Form1 から MyClock に変更します。この変更は Display.Designer.cs に自動的に反映されます。
全てのファイルが変更されたので、[F5] を押して、ビルドとデバッグモードでの実行を行います。
なお、ビルドする際に変更されたファイルは上書き保存されます。

これで下準備終了です。
3. デジタル時計の部品を追加
時刻を表示するために、ラベルとタイマーの2つの部品を導入します。ラベルは 12:34:56 といった文字列を表示するための部品、タイマーは現在の時刻を取得するための部品です。
そして、タイマーで1秒ことに時刻と取得し、その結果をラベルに表示するように仕上げてゆきます。
ところで、Windows アプリは、四角い領域を視覚的に表示したウィンドウから構成されるのが基本です。タイトルバー付きのウィンドウ (C# や VB ではフォームという) であれ、ボタンであれ、文字列入力用のエディットボックス (C# や VB ではテキストボックスと言う) だろうと、全てウィンドウであって、味付けが違うだけです。
フォームに貼り付ける部品には、他にもメニューバーやツールバーなどがあります。タイマーも視覚効果は無いけれど部品の1つです。
▶ 部品の登録
Visual Studio (の左) にツールボックスがあり、そこには様々な部品が準備されています。これをウィンドウにドラッグ&ドロップすることで、これらのサブクラス化、インスタンス生成、宣言や定義などの初期的なコードが自動的に追記されます。
今回は、時間表示用に ラベル(コモンコントロール)とタイマー (コンポーネント) を使うことにします。
左にあるツールボックスをクリックて一旦ピン止めし、ラベルとタイマーをドラッグ&ドロップするとこんな感じになります。

フォーム内に label1 があり、フォーム外の下に timer1 があります。
この段階で、Display.cs と Program.cs は変更されず、
DisplayDesigner.cs では多くのコードが自動生成されているのが分かります。
namespace MyClock
{
partial class Display
{
/// <summary>
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows フォーム デザイナーで生成されたコード
/// <summary>
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.label1 = new System.Windows.Forms.Label();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(101, 64);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(35, 12);
this.label1.TabIndex = 0;
this.label1.Text = "label1";
//
// Display
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 261);
this.Controls.Add(this.label1);
this.Name = "Display";
this.Text = "MyClock";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Timer timer1;
}
}
ここでは、上の方でアプリケーション終了時に各部品を解放する処理、それ以下で追加した部品の定義とデフォルトのプロパティの設定が記述されています。
▶ ラベルとフォームのプロパティ設定
ラベルとフォームのプロパティを設定して、以下のような外観にします。

先ずはラベルの設定:
ラベルをクリックすると(右下に)ラベルのプロパティが表示されるので、そこで以下のように変更しますます。
- デザイン - (Name) を currentTime
- 配置 - Dock を Fill
- 表示 - Font を MS UI Gothic のまま 36pt、太文字
- 表示 - Text を 12:34:56
- 配置 - Size は 192, 48 (マウスで大きさを調整するとこのくらいになる)
Doc を Fill にすることで、ラベルがフォームにうまく張り付きます。
次は、フォームの設定:
フォームのタイトルバーをクリックすると(右下に)フォームのプロパティを表示されるので、そこで以下のように変更します。
- ウィンドウ スタイル - Opacity を 50%
- ウィンドウ スタイル - TopMost を True
- デザイン - (Name) は Display になっている筈
- 表示 - FormBoderStyle を FixedToolWindow
- 表示 - Text は MyClock になっている筈
- 配置 - Size は 207, 85 (マウスで大きさを調整するとこのくらいになる)
では、[F5] を押して、ビルドとデバッグモードでアプリを実行をすると、

こんな感じで、アプリが起動します。半透明で最前面表示になっていることを確認します。
右上の[X]ボタンをクリックすれば終了。なおデバッグモードで実行している時は、
- █ [デバッグの停止]ボタンを押すか、
- メニューで [デバッグ(D)] - [█ デバッグの停止] を選ぶ
これで外観ができたので、時刻を表示する機能を作ります。
▶ タイマーの設定
タイマーは 1 Tick が 1 ms (ミリ秒) です。1秒ごとに数字が変わるデジタル時計を作るのでタイマーの間隔 (Interval) は 1000 ms になります。そこで、タイマーの名前を secTimer に変更します。すると、タイマークラスの名前が自動的に secTimerに変更されます。
実際の作業は、ドラッグ&ドロップした timer1 をクリックして、(右下にある) timer1 のプロパティを変更することです。
- デザイン - (Name) を secTimer
- 動作 - Enabled を True (これを忘れるとタイマーは動作しない)
- 動作 - Interval を 1000
▶ 現在の時刻を表示させる方法
ここまで一切コーディングせずに進めてきましたが、これ以降は実際にコードを書く必要があります。
Windowsプログラミングでは、発生したイベントを捕らえて、そこで必要な処理を記述するのが基本です。これは、ある単独の処理がCPUを占有しないための方策です。そうしないとマルチタスク処理が破綻してしまいます。
イベントを捕らえて必要な処理を行う部分をイベントハンドラと呼びます。
今回は、タイマーイベントが 1000 ms (=1秒) ごとに発生するのを利用します。タイマーイベントハンドラを作り、その中で現在の時刻をラベルに渡すようにコーディングするだけです。
▶ タイマーイベントハンドラの作成
既に、secTimer という名前 (クラス名) でタイマーを作りました。

secTimer コントロールを、マウスの左ボタンでダブルクリックします。すると、自動的にイベントハンドラのテンプレートを作成し、それを表示してくれます。

▶ 現在の時刻をラベルに渡す
コモンコントロールという視覚的に機能する部品は、データを受け取って表示する機能があります。
例えば、文字列を受け取れるコントロールに文字列を渡すには、以下のようにコーデイングします。
(コントロールのクラス名).Text = "文字列";
今回は currentTime と名前をつけたラベルコントロールに時刻の文字列を表示させるので、
currentTime.Text = (現在時刻の文字列);
とすれば良いわけです。currentTime クラスはラベルの基本クラスから全ての機能を引き継いでいて、Text プロパティも引き継いでいます。上の作業で自動的に作成された MyClockDesinger.cs には、この引き継ぎに必要なコードとプロパティ設定のコードが含まれています。
具体的には、
//
// currentTime
//
の下に currentTime に必要な処理が書かれています。
さて (現在時刻の文字列)を取得するには、DateTime クラスを利用します。DateTime クラスには Now というプロパティがあって、現在時刻を取得してくれます。さらに Now に対して ToSring() 関数も使えるようになっていて、これは時刻を書式に従って文字列に変換してくれます。つまり、
DateTime.Now.ToString("HH:mm:ss");
と書けば、現在時刻の文字列を返します。
従って、
currentTime.Text = DateTime.Now.ToString("HH:mm:ss");
の1行で、ラベルに現在時刻が渡されます。
Private void secTimer_Tick(object sender, EventArgs e)
{
currentTimer.Text = DateTime.Now.ToString("HH:mm:ss");
}
それでは、[F5] を押して、ビルド後にデバッグモードで実行してみます。一応時計として動作しますが、起動直後の一瞬だけ以下の表示になります。

起動直後は、タイマーイベントハンドラが働かないのが原因です。
▶ フォームの描画
タイマーイベントが発生する時(1秒ごと)に現在時刻の表示を行うようにコーディングしました。それ以外のタイミングでは時刻を表示しません。そしてフォームが表示されると同時にタイマーイベントが発生する保証はありません。
そこで、MyClock を起動し、そのフォームが描画されるタイミングで時刻表示をさせれば、問題が解決しそうです。フォームの描画はメッセージ を受け取ることで動作するのが Windows プログラムの基本なので、フォームを描画するイベントを捕らえて、現在時刻をラベル currentTime に渡せば良さそうです。
C# で最初に自動で作成されるソースコードには、フォーム描画のイベントハンドラが自動作成されていないので、自分で作る必要があります。タイマーイベントハンドラを作ったのと同様に、マウス操作だけでフォーム描画するイベントハンドラのテンプレートが作れます。
MyClockのフォーム (Display) のデザイナー画面を開きます。
- ソリューションエクスプローラで Display.cs をダブルクリックするか、
- ソリューションエクスプローラで Display.cs を右クリック - [ビューデザイナー(D)] を選ぶ


Display.cs [デザイン] (フォームデザイナー) が開いたら、タイトルバーあたりをダブルクリックします。

すると、イベントハンドラのテンプレートが自動作成され、そのコードが表示されます。

今自動作成されたイベントハンドラの中に
currentTime.Text = DateTime.Now.ToString("HH:mm:ss");
をコーディングすれば、フォーム描画時に現在の時刻が表示されます。
private void Display_Load(object sender, EventArgs e)
{
currentTime.Text = DateTime.Now.ToString("HH:mm:ss");
}
では、[F5] を押して、ビルドと実行をします。

フォームが表示された直後から正しく時刻を表示されていることが確認できます。
▶ コードの重複を避ける
取り敢えず機能面では完成ですが、少し気になることがあります。Display.cs のコードを眺めてください。

ラベル currentTime に現在時刻を渡すコード
currentTime.Text = DateTime.Now.ToString("HH:mm:ss");
が、そのまま2カ所に記述されています。機能追加やプログラムの複雑化に備えて、関数に置き換えることにします。時刻を表示する関数なので、DisplayTime() とします。
DislayTime() の中に、この1行のコードを入れます。

念のため [F5] を押して動作確認します。
⇒ MyClock Ver 0.10 を作る (2/2)
応援クリックをお願いします。励みになるので...
- 関連記事
-
-
初めて作る C# プログラム - MyClock 2019/05/03
-
C# で MyClock Ver 0.10 を作る (2/2) 2017/01/31
-
C# で MyClock Ver 0.10 を作る (1/2) 2017/01/31
-