C# で MyClock Ver 0.10 を作る (1/2)

プログラム電卓のためのC#プログラミング
e-Gadget

<MyClock トップへ戻る>


2017/01/31

初めて作る C# プログラム - MyClock


MyClock Ver 0.10を作る (1/2)

仕 様
  • フォントが大きい
  • 時計は半透明で常に前画面表示


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]キーを押す
  • ツールバーの[ 開始]ボタンを押す
  • メニューで、[デバッグ] - [デバッグの開始] を選ぶ
ソースファイルが変更された状態でデバッグを始めると、先にビルドが行われてからデバッグが始まります。従って [F5] を覚えておけば、キーを押すだけでビルドとデバッグ開始になるので便利です。

素のMyClock 
素のウィンドウが既にできています。最小化ボタン、最大化ボタン、中止ボタン、システムメニューを出すアイコン、プログラムのタイトル 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 は Visal 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.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
これら3つのファイル内に記述されている内容では、フォーム名とクラス名が Form1 から Display に変更されています。自動処理に任せるとフォーム名とクラス名が同じになります。どうしてもこれらを違う名前にする必要性が無い限り、この作法に従うことにします。

上記以外のファイル名も変更されているのは、ソリューションエクスプローラで確認できます。
Ver1.00ソリューションエクスプローラ 

Display.cs [デザイン] で表示されるフォームのタイトルバーは、まだ Form1 となっています。これはフォーム名やクラス名とも無関係で、単にフォームのテキスト (Display.Text) の設定が Form1 のままになっているためです。これは、フォームのプロパティで変更できます。プログラム中で変更するには Text プロパティを使って、

Display.Text = "変更する文字列";

とします。タイトルバーに表示するテキストをアプリの状況に応じて動的に変更したい時に使えます。

今回は、フォームのテキストを Form1 から MyClock に変更してみます。Display.cs[デザイン]を表示して、フォームをクリックすると、Displayフォームのプロパティ一覧が(右下に)表示されるので、そこで Text というキーを探して、Form1 から MyClock に変更します。この変更は Display.Designer.cs に自動的に反映されます。

全てのファイルが変更されたので、[F5] を押して、ビルドとデバッグモードでの実行を行います。
なお、ビルドする際に変更されたファイルは上書き保存されます。

Displayフォーム 
これで下準備終了です。


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>
  /// <param name="disposing">マネージ リソースを破棄する場合は true を指定し、その他の場合は false を指定します。
  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;
 }
}

ここでは、上の方でアプリケーション終了時に各部品を解放する処理、それ以下で追加した部品の定義とデフォルトのプロパティの設定が記述されています。


ラベルとフォームのプロパティ設定

ラベルとフォームのプロパティを設定して、以下のような外観にします。

Ver1.00外観作成 

先ずはラベルの設定:
ラベルをクリックすると(右下に)ラベルのプロパティが表示されるので、そこで以下のように変更しますます。
  1. デザイン - (Name) を currentTime
  2. 配置 - Dock を Fill
  3. 表示 - Font を MS UI Gothic のまま 36pt、太文字
  4. 表示 - Text を 12:34:56
  5. 配置 - Size は 192, 48 (マウスで大きさを調整するとこのくらいになる)
Text を 12:34:56 とすることで実際に時刻が表示された時のラベルのサイズを調整できます。
Doc を Fill にすることで、ラベルがフォームにうまく張り付きます。


次は、フォームの設定:
フォームのタイトルバーをクリックすると(右下に)フォームのプロパティを表示されるので、そこで以下のように変更します。
  1. ウィンドウ スタイル - Opacity を 50%
  2. ウィンドウ スタイル - TopMost を True
  3. デザイン - (Name) は Display になっている筈
  4. 表示 - FormBoderStyle を FixedToolWindow
  5. 表示 - Text は MyClock になっている筈
  6. 配置 - Size は 207, 85 (マウスで大きさを調整するとこのくらいになる)
Opacity 50% で半透明になり、TopMost True で最前面に表示されます。

では、[F5] を押して、ビルドとデバッグモードでアプリを実行をすると、

Ver1.00外観 

こんな感じで、アプリが起動します。半透明で最前面表示になっていることを確認します。

右上の[X]ボタンをクリックすれば終了。なおデバッグモードで実行している時は、
  • [デバッグの停止]ボタンを押すか、
  • メニューで [デバッグ(D)] - [デバッグの停止] を選ぶ
ことで、アプリを強制的に終了できます。

これで外観ができたので、時刻を表示する機能を作ります。


タイマーの設定

タイマーは 1 Tick が 1 ms (ミリ秒) です。1秒ごとに数字が変わるデジタル時計を作るのでタイマーの間隔 (Interval) は 1000 ms になります。そこで、タイマーの名前を secTimer に変更します。すると、タイマークラスの名前が自動的に secTimerに変更されます。

実際の作業は、ドラッグ&ドロップした timer1 をクリックして、(右下にある) timer1 のプロパティを変更することです。
  1. デザイン - (Name) を secTimer
  2. 動作 - Enabled を True  (これを忘れるとタイマーは動作しない)
  3. 動作 - Interval を 1000
フォーム、ラベルそしてタイマーのプロパティの設定を変更した結果は、全て DisplayDesigner.cs に反映されています。チョット眺めてみると、それぞれのクラスとメソッド(関数)の使い方のヒントが得られて大いに参考になると思います。但し、くれぐれも不用意な編集・変更には注意しましょう。


 現在の時刻を表示させる方法

ここまで一切コーディングせずに進めてきましたが、これ以降は実際にコードを書く必要があります。

Windowsプログラミングでは、発生したイベントを捕らえて、そこで必要な処理を記述するのが基本です。これは、ある単独の処理がCPUを占有しないための方策です。そうしないとマルチタスク処理が破綻してしまいます。

イベントを捕らえて必要な処理を行う部分をイベントハンドラと呼びます。

今回は、タイマーイベントが 1000 ms (=1秒) ごとに発生するのを利用します。タイマーイベントハンドラを作り、その中で現在の時刻をラベルに渡すようにコーディングするだけです。


タイマーイベントハンドラの作成

既に、secTimer という名前 (クラス名) でタイマーを作りました。

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] を押して、ビルド後にデバッグモードで実行してみます。一応時計として動作しますが、起動直後の一瞬だけ以下の表示になります。

Ver1.00外観 

起動直後は、タイマーイベントハンドラが働かないのが原因です。


フォームの描画

タイマーイベントが発生する時(1秒ごと)に現在時刻の表示を行うようにコーディングしました。それ以外のタイミングでは時刻を表示しません。そしてフォームが表示されると同時にタイマーイベントが発生する保証はありません。

そこで、MyClock を起動し、そのフォームが描画されるタイミングで時刻表示をさせれば、問題が解決しそうです。フォームの描画はメッセージ を受け取ることで動作するのが Windows プログラムの基本なので、フォームを描画するイベントを捕らえて、現在時刻をラベル currentTime に渡せば良さそうです。

C# で最初に自動で作成されるソースコードには、フォーム描画のイベントハンドラが自動作成されていないので、自分で作る必要があります。タイマーイベントハンドラを作ったのと同様に、マウス操作だけでフォーム描画するイベントハンドラのテンプレートが作れます。

MyClockのフォーム (Display) のデザイナー画面を開きます。
  • ソリューションエクスプローラで Display.cs をダブルクリックするか、
  • ソリューションエクスプローラで Display.cs を右クリック - [ビューデザイナー(D)] を選ぶ
MyClock.cs 

ビューデザイナーを開く
 


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


Displayビューデザイナ 

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

フォームイベントハンドラ 

今自動作成されたイベントハンドラの中に

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] を押して、ビルドと実行をします。

MyClock2

フォームが表示された直後から正しく時刻を表示されていることが確認できます。


コードの重複を避ける

取り敢えず機能面では完成ですが、少し気になることがあります。Display.cs のコードを眺めてください。

フォーム描画イベントハンドラ完成


ラベル currentTime に現在時刻を渡すコード

currentTime.Text = DateTime.Now.ToString("HH:mm:ss");

が、そのまま2カ所に記述されています。機能追加やプログラムの複雑化に備えて、関数に置き換えることにします。時刻を表示する関数なので、DisplayTime() とします。

DislayTime() の中に、この1行のコードを入れます。

Display_cs完成

念のため [F5] を押して動作確認します。


 MyClock Ver 0.10 を作る (2/2)







応援クリックをお願いします。励みになるので...
にほんブログ村 IT技術ブログ 開発言語へ



    

keywords: プログラム関数電卓、Windowsプログラミング

リンク集 | ブログ内マップ

関連記事

テーマ : プログラム関数電卓
ジャンル : コンピュータ

コメントの投稿

非公開コメント

最新記事
最新コメント
カテゴリ
C# (3)
検索フォーム
Visitors
Online Counter
現在の閲覧者数:
プロフィール

やす (Krtyski)

Author:やす (Krtyski)
since Oct 30, 2013


プログラム電卓は、プログラムを作って、使ってナンボ!

実際に触って気づいたこと、自作プログラム、電卓プログラミングについて書いています

おもしろい・役に立つならクリックしてください。励みになります。
にほんブログ村 IT技術ブログ 開発言語へ
にほんブログ村


人気ブログランキングへ


FC2ブログランキングへ


写真: 「4駆で泥んこ遊び@オックスフォード郊外」

リンク
月別アーカイブ
Sitemap

全ての記事を表示する

RSSリンクの表示
最新トラックバック
ブロとも申請フォーム

この人とブロともになる

QRコード
QR