30
 バインドとイベント名 



本セクションに関連するものとして イベント処理 でも解説を行っているので併せてお読みください。


 
 
バインドの概念
 
 

 今までの解説で既に、イベントをMind処理単語に結び付ける方法を書いてきました。それらのプログラムはボタンやメニュー項目を押すことで発生するイベントの登録を”ウィジェットへの属性付与”として扱っていました。つまり、
   ”ウィジェットからのイベント発生”
を登録するものでした。
 しかし他にもキーの打鍵やマウスのクリックなど、
   ”生のイベントそのものを扱う”
仕組みがあります。このセクションではそれについて解説します。
 キー打鍵やマウスボタン押下などの各種イベントを特定の処理に結び付けることを”バインド”と呼びます。たとえば "Esc"キー打鍵で何らかの処理を行わせたり、マウスの左クリックをMindの処理単語に関連付けたりできます。
 ダイアログ、メニュー、テキストウィジェット、キャンバスなどでバインドが使われることが多いですが統合してここで解説します。
 まずサンプル "hellowinButton.exe" を実行してみてください。

 ボタンが1つ表示されます。ここでTABキーを押すとボタンが点線で囲まれフォーカスが当たったことが分かります(これ自体はGUIエンジンが勝手にやっていることです)。

 この状態でEnterキーを押してみてください。何も起きません。つまりデフォルトではボタンにフォーカスが当たっている状態であってもEnterキーには無反応です。
注:フォーカスを当てることについては、「ウィンドウ操作」-「フォーカスを当てる」 を参照してくたさい。
 次に、サンプル "focus-and-bind.exe" を実行します。

 上でボタン1、ボタン2を押してみてください。イベントが発生しメッセージ域に、
    ボタンが押されました
    引数="ボタン1押下"
と表示されます。
 今度は Enterキーを押してみてください。Enterキーでイベントが発生する様子が確認できます。
    ボタンが押されました
    イベント名="Enter" 引数="Event-1"
と表示され、先のボタン押下とは反応が違うことが分かります。
 さらにTABキーによってフォーカスをボタン2に移動させそこでEnterキーを押すと今度は
    ボタンが押されました
    イベント名="Enter" 引数="Event-2"
と表示されます。
 さて、ボタンにフォーカスが当たっている状態でEnterキーを押すと、ボタン押下と同じ扱いになる・・というのはWindowsのアプリケーションとして当然だと思われるかも知れません。それはそうなのですが、それはWindows OS や本GUIエンジンが自動的にやってくれるわけではなく、アプリケーションが明にEnterキー扱いを指示する必要があります。つまり、バインドを登録する必要があります。
 さらに、"focus-and-bind.exe" で注目して欲しいのは、このアプリケーションが起動したときにボタン1にフォーカスが当たっている点です。これもプログラムで明にフォーカスを与えています。この状態でEnterキーを押すと、あらかじめ登録しておいたイベントが発生する仕組みになっています。
 TABキーを押すとフォーカスがボタン1とボタン2の間で交互に移動するので、Enterをどちらのボタンに効かせるか選ぶことができます。TABキーによるフォーカス移動については、GUIライブラリが自動的に行ってくれるのでプログラムで明に書く必要はありません。(もちろんプログラムで明にフォーカスを当てることもできます)
 さらに続けます。キーボードから Ctrl-s を打鍵してみてください。
    ボタンが押されました
    イベント名="Ctrl-s" 引数="Event-s"
と表示され、Ctrl-s キーの押下がイベンを引き起こしたことが分かります。これもまたそのようなバインドを登録したので起きたことです。


 
 
キーイベントのバインド
 
 

■キーイベントのバインドを登録
 キー押下やマウスボタンなど、生のイベントをMindの処理単語にバインドする機能です。

構文=
(ステップ1:バインドの登録)     <イベント名>と       <イベント処理の実行情報>と <イベント引数>と         <対象ウィジェットID>で           キーイベントのバインドを登録 → ・ (ステップ2:イベント発生時に渡されるパラメータ)      ↓登録時引数が空列のとき      スタック→ イベント名、 1(引数個数)      ↓登録時引数が非空列のとき      スタック→ イベント名、 引数1,引数2,・・、 n(引数個数)                                                     ユーザ引数個数+1 (ユーザ引数が1個なら2)

       プログラム例1:(focus-and-bind.src から抜粋)
    「Ctrl-s」と
     キーイベント処理の 実行情報と 「Event-s」と
      メインウィンドウで
       キーイベントのバインドを登録する
 上記のようにキー入力に対応するイベント処理を登録します。
 上記例で最初にスタックに積んでいる文字列「Ctrl-s」はイベント名としてのキーシンボルです。(イベント名の詳細は後にまとめて解説します)
 スタックにはさらに、イベント処理語の実行情報と引数を積み、さらに動作対象となるウィジェットのIDを積み、最後に「キーイベントのバインドを登録」を呼び出しています。
 イベント引数は文字列で、
     「abc」を ・・
のように指定します。複数の引数は
     「abc def」を ・・
のように空白で区切って並べてください。
 引数に空白文字を含む場合には、
     「"ab c" def」を ・・
のように指定してください。
 なお、引数(群)文字列末尾に \ 記号は付けられません。また、{ } 記号は使えるものの、開きと閉じでバランスが取れている必要があります。(アンバランスで使うとエラーを検出します)
 対象ウィジェットIDですが、上記は「メインウィンドウ」を指定しています。”メインウィンドウのどこかにフォーカスがあれば可”という意味になります。
 次の例はどうでしょうか。
       プログラム例2:(focus-and-bind.src から抜粋)
    「Enter」と
     ボタン押下処理の 実行情報と 「Event-1」と
      ボタン1で      ←★注目
       このイベントのバインドを登録する
 例1では対象ウィジェットを「メインウィンドウ」としていたのに比べ、例2では対象ウィジェットを「ボタン1」としています。Enterキーはフォーカスの当たっているウィジェットをアクティブ化する・・という使われ方が多いため、キーイベントをボタンという狭い領域に対応させます。

■キーイベントのサンプルプログラム
 キーイベントのバインド登録のサンプルプログラムとしては、
focus-and-bind.exe
ボタンをEnterキーにバインドする簡単なもの
bind-keys.exe
多くのキーバインドをテストする大規模なもの
を参考にしてください。


 
 
マウスイベントのバインド
 
 

■マウスイベントのバインドを登録
 マウス操作のイベントをMindの処理単語にバインドします。


構文=
(ステップ1:バインドの登録)     <イベント名>と       <イベント処理の実行情報>と <イベント引数>と         <対象ウィジェットID>で           マウスイベントのバインドを登録 → ・           マウスイベント名:(下記左辺のシンボルで指定)               左クリックは    文字列定数 「Button-1」               左ダブルクリックは 文字列定数 「Double-1」               右クリックは    文字列定数 「Button-3」               左リリースは    文字列定数 「ButtonRelease-1」               右リリースは    文字列定数 「ButtonRelease-3」               左ドラッグは    文字列定数 「B1-Motion」               右ドラッグは    文字列定数 「B3-Motion」               Ctrl-左クリックは  文字列定数 「Control-Button-1」               Shift-左クリックは 文字列定数 「Shift-Button-1」               Ctrl-右クリックは  文字列定数 「Control-Button-3」               Shift-右クリックは 文字列定数 「Shift-Button-3」 (ステップ2:イベント発生時に渡されるパラメータ)      ↓登録時引数が空列のとき      スタック→ イベント名、              X座標(文字列)、Y座標(文字列)、3(引数個数)      ↓登録時引数が非空列のとき      スタック→ イベント名、              X座標(文字列)、Y座標(文字列)、                 引数1,引数2,・・、  n(引数個数)                                                              n=ユーザ引数個数+3                           (ユーザ引数が1個なら4)
       プログラム例3:(bind-mouse.src から抜粋)
このマウス操作をバインド登録とは (イベント名 → ・)
   (イベント名と)
      マウスイベント処理の 実行情報をつみ
        空列をつみ    ←ここではイベント引数を使わないので空列
          メインウィンドウをつみ
    マウスイベントのバインドを登録する。

数多くのマウス操作をバインド登録とは (・ → ・)
    左クリックを    このマウス操作をバインド登録する
    左ダブルクリックを このマウス操作をバインド登録する
    〜略〜
 イベント発生時に処理単語に渡されるパラメータのうちX座標とY座標は対象ウィジェット左上隅からの相対です。さらには、その”座標”は数値ではなく数値を表す文字列なので要注意です。
 文字列としての座標値は、たとえば、
     ↓文字列を          ↓数値に
     X座標列を 数値変換し 捨て X座標に 入れ
のようにして整数値を得てください。
 マウスイベントはキャンバスとの組み合わせで使われることが多いです。「キャンバス」−「図形の特定・検索」 で改めて解説します。
 イベント引数は文字列で、
     「abc」を ・・
のように指定します。複数の引数は
     「abc def」を ・・
のように空白で区切って並べてください。引数に空白文字を含む場合には
     「"ab c" def」を ・・
のように指定してください。
 なお、引数(群)文字列末尾に \ 記号は付けられません。また、{ } 記号は使えるものの、開きと閉じでバランスが取れている必要があります。(アンバランスで使うとエラーを検出します)

■マウスイベントのサンプルプログラム
 マウスイベントのバインド登録のサンプルプログラムとしては、
    bind-mouse.exe
 を参考にしてください。

■マウスのイベント処理
 マウスイベントをバインドすると登録しておいた処理単語か呼び出されます。
 たとえば次のような書き方が考えられます。
       プログラム例4:
マウスイベント処理とは (イベント名、X座標列、Y座標列、3(パラメータ数) → ・)
        イベント名は 文字列
        X座標列は  文字列 ※文字列形式の座標
        Y座標列は  文字列
        X座標は   変数  ※整数形式の座標
        Y座標は   変数
    (パラメータ数が) 3と 異なる
        ならば 「マウスイベント処理においてパラメータ数誤り」で
            重大エラー
        つぎに
    イベント名と X座標列と Y座標列に 入れ

	X座標列を 数値変換し 捨て X座標に 入れ
	Y座標列を 数値変換し 捨て Y座標に 入れ

    イベント名が 左クリックに 等しい文字列
        ならば ※−−−−−−−※
            ※ 左クリック ※
            ※−−−−−−−※
            ・・左クリック時の処理・・
        さもなければ
            〜略〜

 処理単語「マウスイベント処理」が起動された段階で以下ようなスタック並びとなります。
     → イベント名、X座標列、Y座標列、3(引数個数)
 スタックパラメータのうちイベント名ですが、上記で、
     左クリックに 等しい文字列
 という記述に注目してください。上がって来るイベント名は文字列の "Button-1" なので、たとえば、
     "Button-1"に 等しい文字列
と書いても良いのですが、それではソースの意図が分かりにくいだけでなく、たとえば
     "Buttn-1"に 等しい文字列   ←'o'が抜けている
と書いた場合にコンパイル時にも実行時にもエラーにならず動作不良の原因が分からない事態も考えられます。
 したがって、できるだけMindのシンボルとして、
     左クリックに 等しい文字列
と書くことをお勧めします。「左クリック」の綴りを間違えれば、コンパイル時に未定義語というエラー検出がされます。
 次に、座標値ですが、
 スタック奥から2番目と3番目の座標は整数ではなく、”整数を表す文字列”であることに注意します(イベント引数はすべて文字列です)。
 上記プログラム例も、一旦文字列変数に格納した後に、それを整数化して整数変数に代入しています。

■独特のマウスイベントについて
 以下はサンプルプログラム "bind-mouse.exe" を試しながらお読みください。

<<ダブルクリック>>
ダブルクリックすると以下のイベントが発生します。

      (イベント処理語に入ったときのスタック内容)
      (→ イベント名、座標X、座標Y の順   )
  (ダブル1回目)
    イベント引数: Button-1 | 264 | 190
    イベント引数: ButtonRelease-1 | 264 | 190
  (ダブル2回目)
    イベント引数: Double-1 | 264 | 190
    イベント引数: ButtonRelease-1 | 264 | 190
「ダブルクリックした」という1つのイベントが上がるわけではない点にご注意ください。イベント発生は、
    プレス  (イベント名=Button-1)
    リリース
    プレス  (イベント名=Double-1)
    リリース
という現れ方になります。
 特徴的なことは、1回目ボタン押下が Button-1 であり、2回目ボタン押下が Double-1 となっていることです。(Mindシンボルで言えば「左クリック」と「左ダブルクリック」)
 プログラムとしてイベント処理を書く際、 Button-1 のイベントが上がった時点では 「シングルクリックの Press」 なのか 「ダブルクリックの Press」 なのかは判別できず、 2回目プレスの Double-1 イベントが来た時点でようやく 「ダブルクリックだった」 と分かることになります。
 したがって、ダブルクリックをサポートするアプリケーションでは、何らかの対処が必要となります。
 なお、リリースタイミングでのイベントについは、ドラッグ操作を別とすれば、リリースイベントはあえて見なくても良いでしょう(イベントは受け取るが無視する)。

<<ドラッグ>>
 左ボタンでドラッグすると以下のイベントが発生します。
    イベント引数: Button-1 | 197 | 152        ←左クリック
    イベント引数: B1-Motion | 201 | 157       ←ドラッグ(1)
    イベント引数: B1-Motion | 203 | 161       ←ドラッグ(2)
    〜略〜
    イベント引数: B1-Motion | 206 | 166       ←ドラッグ(N)
    イベント引数: ButtonRelease-1 | 208 | 171  ←左リリース
 ドラッグ開始時のイベントは、一見すると普通のクリックイベントであることに注意します。ドラッグをサポートするアプリケーションにおいては、左クリックのイベントが上がった時点では、それが単なる左クリックなのかドラッグ開始の左クリックなのかは判別できません。
 これを解決する手段としてリリースイベントを見る方法があります。たとえば左クリック時点では処理を保留しておき、その次にドラッグイベントが来るか、あるいは(左クリックとしての)リリースが来るかで処理を分岐することで判別が可能となります。
 当然ではありますが、左ドラッグ の終了タイミングは 左リリース となります。右ドラッグ の終了タイミングは 右リリース となります。
記:キャンバスのサンプルプログラム "canvas-event" では図形をドラッグすることて移動をおこなうことができます。ソースコードを参考にしてください。

■マウスイベントを適用するウィジェット
 マウスでオブジェクトを操作するという意味で、キャンバスウィジェット内で利用することが多いかと思います。しかし、マウスイベントの適用先として、キャンバスウィジェットに限らず、ラベルウィジェットやテキストウィジェットなど何にでも適用できます。
 テキストウィジェット中でマウスを操作することはよくあることなのですが、テキストウィジェット自体がデフォルトで持つマウス処理で間に合ってしまうため、プログラマが明にマウスイベントを扱う必要はほとんどありません。
 たとえば、テキストウィジェット中の数文字をマウスでドラッグして反転させ、Delキーを押すとその文字群を削除できます。しかしそれについてユーザプログラムとして何も書く必要は無く、テキストウィジェットのデフォルトの動作として自動的に実現されます。逆に言えば、それだけテキストウィジェットが提供するサービスは大きいと言えます。
 一方、キャンバスウィジェットについてはマウスへの自動処理はまったくありません。マウスで図形を操作するにはマウスイベント扱いをすべてユーザプログラムで組む必要があります。(キャンバスウィジェットの章を参照してください)


 
 
汎用イベントのバインドを登録
 
 

 キー押下でもなくマウス操作でもないその他のイベントをMindの処理単語にバインドします。

■汎用イベントのバインドを登録

構文=
(ステップ1:バインドの登録)     <イベント名>と       <イベント処理の実行情報>と <イベント引数>と         <対象ウィジェットID>で           汎用イベントのバインドを登録 → ・ (ステップ2:イベント発生時に渡されるパラメータ)      ↓登録時引数が空列のとき      スタック→ イベント名、 1(引数個数)      ↓登録時引数が非空列のとき      スタック→ イベント名、 引数1,引数2,・・、 n(引数個数)                                                     ユーザ引数個数+1 (ユーザ引数が1個なら2)


 
 
キーイベントを発生
 
 

この機能はテキストウィジェットやキャンバスウィジェットでよく使われるものです。以下ではテキストウィジェットでの利用を例に説明しているので、テキストウィジェットの解説を読み終わってから本項を読まれるのも良い方法です。
 キー打鍵など、あるイベントに対して既に特定の処理が定義されているか、あるいはウィジェット自身が持つデフォルト処理として対応が存在する場合、プログラムからそのイベントを強制発生することでその処理を行わせることができます。
 たとえば、テキストウィジェットにおいて、Delキー打鍵によりキャレットのある1文字が削除されます(これはウィジェット自身が持つデフォルト編集機能なのでMindで書く必要はありません)。
 一方、たとえば Ctrl-g 打鍵でも同じ動作をさせたいとします。そのとき、
     キャレットのある1文字を削除する
ような具体的な処理をあえて書かず、Delキーのイベントを強制発生させることで簡単に済ませることができます。

構文=
<ウィジェットID>と <イベント名>で キーイベントを発生 → ・
       プログラム例1:
Ctrl-g押下処理とは
    イベント引数を捨て
    テキストボックスと 「Del」で キーイベントを発生させる。
       プログラム例2:
やり直し処理とは (・ → ・)
    テキストボックス記憶と 「Ctrl-z」で キーイベントを発生する。

 〜略〜

項目2のボタン処理とは (1 → ・)
    〜略〜
    _引数1に 入れ
    _引数1が 「やり直し」に 等しい文字列
        ならば やり直し処理し
 上の例2は、サンプルプログラム "text-edit.src" の中で書かれているものです。
 メニューバーの「編集」−「やり直し」が押された時に「やり直し処理」に飛んで来ますが、そこでイベント「Ctrl-z」を発生させることで処理を簡単に済ませています。(Ctrl-z 対応はGUIエンジンのデフォルト編集機能であるためMindで書かれたコードは書かなくて済み、この手法が生きます)


 
 
キー打鍵のイベント名
 
 

 ボタンなどのウィジェットに対してイベントを登録する時はウィジェット名を対象として行いましたが、本章で解説するものは”イベント名”と呼ぶものをイベント発生の元として指定します。
 最初にキー打鍵のイベント名について解説します。

■キーシンボルによるイベント名
 キー打鍵のイベントでバインドを登録する際のイベント名を解説します。
1文字で表せるキーシンボル:
a〜Z 、0〜9、(, ), @ .. などキーの刻印が1文字のものはその刻印自体がイベント名となります (a と A は別扱いなので注意)
ファンクションキー:
F1〜F12 です (Fは大文字、fは誤り)
その他のキー:
Esc, Tab, Enter など数文字の刻印を持つキーです
 上記で「その他のキー」に分類されるものは技術情報やキーボード刻印での表記がまちまちです。
 たとえば Esc/Escape、Ins/Insert のような表記揺れがありますが、本ライブラリは短形式に統一します。したがって、たとえば「Esc」が正く、「Escape」は誤りです。また、「F1」と書くべきところ「f1」と書くものもエラーになります。
   (Mindの単語認識とは異なり、全角・半角・大文字・小文字は区別されます)
注:本ライブラリが内部的に利用しているGUIエンジン(Tcl/Tk)ネイティブのキーシンボルと本ライブラリのMindのソースコードでのキーシンボルは異なります。

■記号あるいは1文字を超えるキーシンボル
 'A'など英字1文字で表せるキーはそれ自体がイベント名となるので問題ないのですが、それ以外のキー、たとえば「Esc」など数文字のキーシンボルや記号1字のキーシンボルは書き方が指定されるのでここにまとめます。
 キーシンボルは文字列定数として記述するため、ソースコード上は下記のように " " または 「 」 で囲むことになります。
  「Esc」
  「Tab」
  「BS」
  「Enter」
  「Print」
  「Pause」
  「Ins」
  「Del」
  「Home」
  「End」
  「Pgup」
  「Pgdow」
  「Left」
  「Up」
  「Right」
  「Down」
  「(」
  「)」
  「=」
  「-」
  「~」
  「^」
  「|」
  「\」
  「`」
  「@」
  「{」
  「[」
  「+」
  「;」
  「*」
  「:」
  「}」
  「]」
  「<」
  「,」
  「>」
  「.」
  「?」
  「/」
  「_」 (underscore)

■キーの修飾
 たとえば「Ctrl-c」という表現は文字キー「c」を「Ctrl」で修飾しています。
 修飾子とキーシンボルはハイフン「-」でつなぎます(+ ではありません)。
   (誤り)
      CTRL   ← Cのみ大文字、trlは小文字にしてください
      Ctrl+c  ← + ではなく - としてください
 このような修飾には以下のものがありますがこの通りに記述してください。
      Ctrl
      Shift
      Alt
 修飾は重複使用できます。
   (例)
      Ctrl-Shift-c
      Alt-Ctrl-Right
 以下に注意願います。


 
 
子ウィンドウが閉じる時のイベント
 
 

 子ウィンドウが閉じるときにイベントを発生させられます。
 ウィンドウ操作関連として、「ウィンドウ操作」−「子ウィンドウが閉じる時の制御」 にて解説しているのでそちらをご覧ください。