画像ファイル
画像ファイル イベント入門
VB.NET C#全般
1羊の皮を着た狼 VB.NET
2Form1、Form2の相互参照
3Form1、Form2の相互参照 2
4VB.NET C# データ型の基本
5VB.NET C# 文字列
6VB.NET タイマー精度
7BackgroundWorkerの魅力1..
8BackgroundWorkerの魅力2..
9VB6のタイマー
10コントロールの配列をインデクサ..
11コントロールの配列はジェネリク..
12インデクサ(C#、VB.NET)
13インデクサでBit操作
14Unicode 入門
15デリゲート入門
16マルチスレッド入門
17イベント入門
18デリゲートとイベント
18インターフェースの基本

RichTextBox関係
1RichTextBoxの不思議
2テキスト色付け高速化計画
3VB.NET RichTextBox1
4VB.NET RichTextBox 2

RS-232C関係
1RS-232Cの基礎
2RS-232Cの何が変わった..
3SerialPortクラス
4Unicode(ユニコード)の壁
5マルチスレッドの壁
6RS-232C サンプルコード
7RS-232CのHEXモニタ
8RS-232C 送信モジュール
9RS-232Cのループテスト
10RS-232Cのピンチェンジ..

Socket通信
1C#、VB2005 でSocket通信
2サーバー 複数接続

プロセス間通信
1プロセス間通信(送信側)
2プロセス間通信(受信側)


質問、意見はこちらに
画像ファイル

イベントとは何か?
ボタンをクリックするとクリックイベントが発生します。
またテキストボックスに文字を入力するとテキストチェンジイベントが発生します。
こんなことは説明されなくても解っているとおっしゃる方が殆どであると思います。
それではイベントはどの様に作られるのでしょうか?
ここではイベントがどの様に作成されるのかコードのサンプルを示しながら説明します。

イベントで時計を作成する
何の変哲も無い時計を考えてみる。
画像ファイル
画像を御覧下さい、プログラムをスタートすると秒単位の時間が表示されます。
時間の表示はメインのテキストをフォームのテキスト両方に表示する。

さて実際のプログラムであるが、時間を表示するフォームとクラス、それと時間を計測する Clockクラス、イベントの引数のEventArgsから派生し、イベントの時間を保持する TimeInfoEventArgsクラスの3つを持つ。
起動フォームはClockのインスタンスを作成してこの中のメソドの Run()を 呼び出す。
呼び出しはフォームのLoadが終わってからとする為、タイマーを使ってタイマー内 から呼び出すものとする。
時間はClockクラスのRun()メソドで計測される。
Run()は無限のループになっていて秒が変わるとイベントが発生する。

VBでイベントを発生には、イベントを発生させるクラスでEventステートメントによりイベントを宣言し、 RaiseEventステートメントによりイベントを発生させる。
VB.NETではイベントの宣言の仕方に2種類あり、
VB.NETのコード
Public Event OnSecondChange(ByVal sender As Object, ByVal ti As TimeInfoEventArgs)
のようにデリゲートを先ず宣言し、其の後にEventステートメントによりイベントを宣言する方法と、
VB.NETのコード
Public Event OnSecondChange(ByVal sender As Object, ByVal ti As TimeInfoEventArgs)
の様にデリゲートとイベントを同時に宣言する方法である。

一方C#ではデリゲートを使ってイベントを発生させる、この方法はVB.NETの始めに書いた方法と同じである。
C#のコード
//デリゲートの宣言
public delegate void SecondChangeHandler(object clock,
TimeInfoEventArgs timeInformation);
//イベントの作成
public event SecondChangeHandler OnSecondChange;

いずれにしろイベントはデリゲートによって実現されることを理解することが重要である。

ループの中のApplication.DoEvents() はループ処理中に、 他のスレッドに処理を回す為のものであり、
System.Threading.Thread.Sleep(2) もループの実行を2mSec休むことにより、CPUの負荷を 下げ、又他のスレッドに処理を回す。

イベントの引数としては、イベント発生元のClockのインスタンスと、EventArgsから継承された、 TimeInfoEventArgsが渡される。
表示される時間はこの中のTimeInfoEventArgsが保持している。
引数にイベント発生元のインスタンスと、EventArgs又はそれの継承されたものを指定するのは、 イベントの慣例であり必然性は無いが、コードを解りや易くするためにも、 慣例を守りたい。

さてイベントを受信する方であるが、イベントの登録は
C#のコード
myClock.OnSecondChange += new Clock.SecondChangeHandler(SecondChanged);
myClock.OnSecondChange += new Clock.SecondChangeHandler(FormTextChange);
VB.NETのコード
AddHandler MyClock.OnSecondChange, AddressOf SecondChanged
AddHandler MyClock.OnSecondChange, AddressOf FormTextChange

でありこの場合は複数登録が可能なことを示す為に、2つのメソドが登録されている。
このイベントの登録は幾つでも登録出来、登録されて順番に実行される。

「イベントはデリゲートのリストを保持するクラス内のフィールドである。」
と言われます、これはどの様な意味でしょうか?
OnSecondChangeはClockクラスの中にあって、リスト形式で、 デリゲートの参照を保持しているのである。
リストは新しくイベントを登録することも、可能であり、実行は登録順に実行される。
C#の場合イベントの登録取り消しに、「-=」を使用するのも興味深いところである。

C#には匿名メソドを言うものが有り、メソドを別に記述しなくても、コードそのものを記述できる。
C#のコード
myClock.OnSecondChange += new Clock.SecondChangeHandler(SecondChanged);
//イベントから呼ばれるメソド
public void SecondChanged(object theClock, TimeInfoEventArgs ti)
{
lblTime.Text = string.Format("{0:00}",ti.hour) +
":" + string.Format("{0:00}",ti.minute) +
":" + string.Format("{0:00}",ti.second);
}
C#のコード

//匿名メソドで記述

myClock.OnSecondChange += delegate(object theClock, TimeInfoEventArgs ti)

{
lblTime.Text = string.Format("{0:00}", ti.hour) +

":" + string.Format("{0:00}", ti.minute) +

":" + string.Format("{0:00}", ti.second);

};

匿名メソドはコードの中に埋め込むもので、最後に「;」が付くので注意されたし。
この匿名メソドを使用するときはSecondChangedのメソドは不要となる。

最後にForm1_FormClosingの中に書かれた、Environment.Exit(0)であるが、
プログラムを終了しようとして×を押しプログラムが終了途中に、再びループが 実行され、プログラムが正常に終了しないことが有る。
Environment.Exit(0)はプログラムを強制的に終了させるメソドである。

C#のコード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace eventc
{
public partial class Form1 : Form
{
//時計のインスタンスを作成
Clock myClock = new Clock();
public Form1()
{
InitializeComponent();
//タイマーで時計をスタートします
timerStart.Enabled=true ;
}

//時計をスタートさせるタイマー
private void timerStart_Tick(object sender, EventArgs e)
{
timerStart.Enabled = false;

//イベントの登録 2つ登録する
myClock.OnSecondChange += new Clock.SecondChangeHandler(SecondChanged);
myClock.OnSecondChange += new Clock.SecondChangeHandler(FormTextChange);
//イベントの登録は下の記述でも良い
//myClock.OnSecondChange += SecondChanged;

//時計をスタート
myClock.Run();
}

//イベントから呼ばれるメソド
public void SecondChanged(object theClock, TimeInfoEventArgs ti)
{
lblTime.Text = string.Format("{0:00}",ti.hour) +
":" + string.Format("{0:00}",ti.minute) +
":" + string.Format("{0:00}",ti.second);
}
public void FormTextChange(object theClock, TimeInfoEventArgs ti)
{
this.Text ="時計"+ string.Format("{0:00}", ti.hour) +
":" + string.Format("{0:00}", ti.minute) +
":" + string.Format("{0:00}", ti.second);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Environment.Exit(0);
}
}

//EventArgsを継承した新しいEventArgs
public class TimeInfoEventArgs : EventArgs
{
//新しいEventArgsのコンストラクタ
public TimeInfoEventArgs(int hour, int minute, int second)
{
this.hour = hour;
this.minute = minute;
this.second = second;
}
//時、分、秒のフィールドを追加
public readonly int hour;
public readonly int minute;
public readonly int second;
}

//時計クラス
public class Clock
{
private int hour;
private int minute;
private int second;

//デリゲートの宣言
public delegate void SecondChangeHandler(object clock,
TimeInfoEventArgs timeInformation);
//イベントの作成
public event SecondChangeHandler OnSecondChange;

public void Run()
{
while(true)
{
//メッセージループの割り込みをさせます。
Application.DoEvents();

//2mSecond 停止します
System.Threading.Thread.Sleep(2);

//現在の時間をセットします
System.DateTime dt = System.DateTime.Now;

//秒が更新されたら
if (dt.Second != second)
{
TimeInfoEventArgs timeInformation =
new TimeInfoEventArgs(dt.Hour, dt.Minute, dt.Second);
//イベントが登録されていたら
if (OnSecondChange != null)
{
//デリゲートを実行
OnSecondChange(this, timeInformation);
}
}
//時間を更新
this.second = dt.Second;
this.minute = dt.Minute;
this.hour = dt.Hour;
}
}
}
}

VB.NETのコード
Option Strict On
Public Class Form1
Private MyClock As New Clock
'上のコードは下のコードでも良い
'Private WithEvents MyClock As New Clock
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load
TimerStart.Enabled = True
End Sub

Private Sub TimerStart_Tick(ByVal sender As System.Object, _
ByVal
e As System.EventArgs) Handles TimerStart.Tick
TimerStart.Enabled = False
'イベントの登録 2つする
AddHandler MyClock.OnSecondChange, AddressOf SecondChanged
AddHandler MyClock.OnSecondChange, AddressOf FormTextChange
MyClock.Run()
End Sub

'イベントから呼ばれるメソド
Public Sub SecondChanged(ByVal theClock As Object, ByVal ti As TimeInfoEventArgs)
LblTime.Text = String.Format("{0:00}", ti.hour) & _
":" + String.Format("{0:00}", ti.minute) & _
":" + String.Format("{0:00}", ti.second)
End Sub
Public Sub FormTextChange(ByVal theClock As Object, ByVal ti As TimeInfoEventArgs)
Me.Text = "時計" & String.Format("{0:00}", ti.hour) & _
":" + String.Format("{0:00}", ti.minute) & _
":" + String.Format("{0:00}", ti.second)

End Sub

Private Sub Form1_FormClosing(ByVal sender As Object, _
ByVal
e As FormClosingEventArgs) Handles MyBase.FormClosing
Environment.Exit(0)
End Sub

End Class

'EventArgsを継承した新しいEventArgs
Public Class TimeInfoEventArgs
Inherits EventArgs
'新しいEventArgsのコンストラクタ
Public Sub New(ByVal hour As Integer, ByVal minute As Integer, _
ByVal
second As Integer)
Me.hour = hour
Me.minute = minute
Me.second = second
End Sub
'時、分、秒のフィールドを追加
Public ReadOnly hour As Integer
Public ReadOnly minute As Integer
Public ReadOnly second As Integer
End Class



'時計クラス
Public Class Clock
Private hour As Integer
Private minute As Integer
Private second As Integer

'イベントの作成

Public Delegate Sub SecondChangeHandler(ByVal sender As Object, _
ByVal
ti As TimeInfoEventArgs)
Public Event OnSecondChange As SecondChangeHandler
'上の2行は下の一行でも良い
'Public Event OnSecondChange(ByVal sender As Object,  _
'ByVal
ti As TimeInfoEventArgs)
Public Sub Run()
While (True)

'メッセージループの割り込みをさせます。
Application.DoEvents()

'2mSecond 停止します
System.Threading.Thread.Sleep(2)

'現在の時間をセットします
Dim dt As System.DateTime = System.DateTime.Now

'秒が更新されたら
If dt.Second <> second Then

Dim timeInformation As TimeInfoEventArgs = _
New TimeInfoEventArgs(dt.Hour, dt.Minute, dt.Second)
'イベントが登録されていたら
Try
'イベントを発生します
RaiseEvent OnSecondChange(Me, timeInformation)
Catch

End Try
End If
'時間を更新
Me.second = dt.Second
Me.minute = dt.Minute
Me.hour = dt.Hour
End While
End Sub
End Class

画像ファイル