イベントとイベントハンドラ

 

ユーザによるキー入力、マウスボタンのクリック、表示内容の変化、状態の変化など、さまざまな状況でイベントが発生します。発生したイベントはイベントキューを経由して対応するイベントハンドラに渡されます。イベントハンドラでは、オブジェクトのプロパティ変更やメソッドの実行などイベントの内容に応じた挙動がユーザアプリケーションで定義できます。

 

 

イベントハンドラは、"On"+イベント名という名前のFunctionとして定義します。CRSの実行エンジンは、イベントの伝播先にこのような名前で定義されているFunctionを探し、イベントを伝播していきます。

 

例)Touchイベントを受け取るイベントハンドラ

 

Function OnTouch(e) {
    Title = "Hello!"; 
}

 

イベントハンドラには、Eventオブジェクトが引数として渡されます。Eventオブジェクトのプロパティによりどのようなイベントが発生したかを調べることができます。

 

e.From                 イベントの発生元オブジェクトのリファレンス

e.Reason             イベントの種類を示す番号

e.EventName       イベントの種類を示す名前

 

例えばテキスト入力でキーボードフォーカスが失われたとき、未入力の場合背景を赤くするためには以下のように記述します。

 

Function OnLostFocus(e) {
    if (e.From instanceOf TextBox) {
        if (e.From.Value == "") {
            e.From.BgColor = $RED;
        } else {
            e.From.BgColor = $STD;
        }
    }
}

 

イベントは、イベントハンドラにより捕捉されるまで"//"Rootオブジェクト)を頂点とするオブジェクトツリーを上位に向かって伝播していきます。

伝播の過程でイベントハンドラにより捕捉されるか、最終的にRootオブジェクトにまで到達したときに消滅します。

 

 

イベントハンドラ内でPostEventメソッドを引数なしで呼び出すことで、イベントハンドラが捕らえたイベントを再度イベントの伝播の流れに戻すことができます。

 

 

イベント処理のタイミング

 

イベントは、常にイベントキューを経由します。イベントキューへのイベント格納と、イベントハンドラの実行は非同期で行われます。

つまり、イベントが発生したタイミングとイベントハンドラが実行されるタイミングは厳密には一致せず、実行時のコンピュータの状態により変動します。例えば、3個の連続したイベントが発生したとき、コンピュータの状況によりイベントハンドラの実行タイミングは、以下のように変動します。

ケース1

1個目のイベントがキューに格納された後、イベントハンドラが起動される。

ケース2

2個目のイベントがキューに格納された後、イベントハンドラが起動される。

ケース3

すべてのイベントがイベントキューに格納された後、イベントハンドラが起動される。

 

通常、イベントの発生は何か状態が変化したとき(例えば、リストボックスの選択位置を変更したときなど)に発生します。連続したイベントは、状態が連続して変化していることになります。上記のケースように連続したイベントで、イベントの要因となった状態をスクリプト中で参照すると、イベントハンドラが実行されるタイミングにより、参照した結果は異なることがあります。

例えば、リストボックスの選択位置変更の場合、ケース1の場合、リストボックスの選択位置を示すValueプロパティを参照すると、1個目のイベントによって設定された値が参照されます。ケース3の場合、3個目のイベントで設定された選択位置が参照されます。最終的にはどのケースでも、イベントと同じ数だけイベントハンドラは起動されますが、オブジェクトプロパティの現在値とイベントを起こしたときの状態は必ずしも一致しないことがある点は、特に注意してください。

 

イベントが発生したときのより詳細な状況を特定する必要がある場合は、イベントハンドラに渡されるEventオブジェクトを参照してください。例えば、前述のリストボックスの例では、イベントオブジェクトのFromプロパティに、そのイベントを起こしたときに選択されているListItemオブジェクトのリファレンスが格納されています。

 

/* 間違った例です。イベント発生時ではなくイベントハンドラ実行時の選択位置を参照しています */
Function OnTouch(e) {
    print("選択位置は", ListBox1.Value, "です\n");
}
 
/* 正しい例です。イベント発生時の選択位置を参照しています */
Function OnTouch(e) {
    print("選択位置は", e.From.Index, "です\n");
}

 

イベントの種類やイベントを起こしたオブジェクトの種類により、さまざまな付随情報がイベントオブジェクトに付加されてイベントハンドラに渡されます。イベントハンドラの実行で、ここで説明したような実行タイミングによる影響を抑止するためには、必ずイベントオブジェクトの付加情報を参照して処理するようにしてください。

 

 

イベントの順序性

 

イベントは、イベントを発生させた動作と同じ順序でイベントキューに格納されます。また、イベントキューに格納されたイベントは、同じ順序で取り出されてイベントハンドラに渡されます。この順序は、常に一定です。

 

しかし、イベントを発生させる動作がいつも同じ順序で行われる保証はありません。例えば、LostFocusイベントの次に、別のオブジェクトのGetFocusイベントが必ず発生するという前提は誤りです。また、画面の操作により発生するイベントと、CRSスクリプトで発行したイベントのどちらが先になるのかも状況により変わるため、特定の発生順序を前提とした処理は誤りです。

 

例えば、Buttonオブジェクトをマウスでクリックしたとき発生する可能性のあるイベントは、GetFocusTouchイベントです。しかし、はじめからButtonにフォーカスがあるときGetFocusは発生しません。また、OnGetFocusイベントハンドラ内で、ユーザ定義イベントを発行したとき、Touchイベントとユーザ定義イベントのどちらが先にイベントキューに格納されるかは不定です。これは、Touchイベントの発生要因となる、マウスボタンを離す操作と、CRSスクリプトの実行でPostEventメソッドを実行する処理で、どちらが先に行われるかを決定する事ができないためです。

 

イベントハンドラは、どのような順序でイベントが発生しても、正しい動作となるように考慮する必要があります。イベントの発生順序に依存する必要がある場合、そのイベントを発行する要因が、常に同じ順序で発生することを検証してください。ただし、Biz/Browserに内蔵されるすべてのクラスは、複数のイベントの発生順序を保障していないため、CRSスクリプトで発行するユーザ定義イベントのみ、発生順序が保障される可能性があります。

 



「オンラインマニュアル」一覧へ戻る
「Bizの宝箱」TOPへ戻る