title: Phi::WinControl
author: YOSHIDA Kazuhiro
mailto: moriq@moriq.com

1. Phi::WinControl

すべての Window Control の基本クラス

1.1. super class

Phi::Control#

1.1. properties

: ime_mode : Fixnum
  constants#ImeMode

: ime_name : String

: parent_ctl3d =

: showing : Boolean
  本当に見えているかどうか。この control が見えていれば，その親は見えており，親の親も見えている。

: tab_order : Fixnum
  tab order とは [Tab] を押したときに focus を受け取る順序のことだ。 form が最初に表示されたとき， tab_order が 0 の Control が focus を得る。特に指定しなくても tab_order は Component が form に追加された順に 0, 1, 2, ... となる。

  各 Component は親の中で unique な tab order をひとつ持つ。これは，ある Component の tab_order を別の Component と同じ値に変更すると，残りのすべての Component の tab_order の値が変わることを意味する。
--ruby
p a.tab_order #==> 6
p b.tab_order #==> 3
p c.tab_order #==> 4

a.tab_order = 3

p a.tab_order #==> 3
p b.tab_order #==> 4
p c.tab_order #==> 5
--
  親に入った Control 数よりも大きい値を指定すると，その Control は最後に回される。それは指定値を受け取らず，確実に最後になるような数値を得る。

  : 注意
    tab_order が意味を持つのは， tab_stop が true で，その Control が親を持つ場合だけだ。 Form の tab_order は，ほかの Form を親として指定しないかぎり使われない。

    tab_order が -1 の Control には親がないので， [Tab] を押してもそれに移ることはできない。

    親 Control を tab order から削除するには， tab_stop を false に設定する。

: tab_stop : Boolean
  タブ操作で移動できるかどうか。

  tab_stop が true ならば self は tab order に入る。 tab_stop が false ならば self は tab order に入らないため，ユーザは Tab を押しても self へ移動できない。

  : 注意
    Form の tab_stop は，ほかの Form を親として指定しないかぎり意味を持たない。

1.1. methods

: focused? : Boolean
  focus があるかどうか。

: begin_drag(immediate, threshold=-1) : nil
  control のドラッグを開始します。

  begin_drag を呼び出すと，ドラッグ操作を開始できます。 Phi::Control#drag_mode が %c:DM_MANUAL% の場合，ドラッグを開始するには begin_drag を呼び出さなくてはなりません。

  : immediate : Boolean
    true ならば，マウスポインタは #drag_cursor に変わり，すぐにドラッグが始まります。 false ならば，マウスポインタは #drag_cursor の値に変わらず， %c:threshold% で指定したピクセル数ほどマウスポインタを移動するとドラッグが始まります。
  : threshold : Fixnum
    呼び出し側が 0 未満の %v:threshold% 値 ( デフォルト値など ) を渡した場合， begin_drag は Mouse#drag_threshold を使います。

  %v:immediate% を false に設定すると， drag and drop または drag and dock 操作を開始する前に Control で mouse click の受け付けができます。

1.1. event handler

: arg1

  以下の記述で戻り値として「arg1」とかかれている場合には、引数の一番目をハンドラの戻り値として返さなければならないことを意味しています。

  メソッド形式の場合には「return key」（arg1 が key の場合）とし、手続きブロック形式の場合にはブロックの最後もしくは break で抜ける直前（※）に「key」と書いて引数を評価する形でシステムに戻します。

  ※　メソッド形式ではメソッド定義の途中で「return key」と書いて抜けることができます。ブロック形式の場合には途中で抜けるには「return」ではなく「break」を使います。他にもスコープの違い、引数の違いなどの違いがあります。（ #on_key_down の説明に両者を対比した例がありますので参考にしてください）。

: on_enter : nil
  control が focus を受け取ったときに呼ばれる。

  enter event は form から form への切り替え時や，その application と別の Windows application との切り替え時には発生しません。

  例えば， Phi::Panel と Phi::GroupBox のように別々の container の中の control 間を切り替えると， container の中の control の enter event の前にその container の enter event が発生します。

  同様に， Container 外の別の Control に focus が移った場合， Container 内の Control の exit event の後で， Container の exit event が発生します。

  例えば， [ OK ] Button の付いた form に 3 つの Phi::RadioButton を持つ Phi::GroupBox があり，その focus が現在 [ OK ] に合っているとします。

  Phi::RadioButton の 1 つが click されたとすると，まず [ OK ] の exit event ，次に Phi::GroupBox の enter event ，そして click された Phi::RadioButton の enter event が発生します。

  この状態から [ OK ] を click すると， Phi::RadioButton の exit event ，次に Phi::GroupBox の exit event ，最後に [ OK ] の enter event が発生します。

: on_exit : nil
  focus が control から別の control へ移ったときに呼ばれる。

  exit event は form から from への切り替え時や，その application と別の Windows application との切り替え時には発生しません。

  : 注意
    #active_control は exit event が発生する前に更新されます。

: on_get_site_info([rect, can_dock], dock_client, pos) : arg1
  control の dock 情報を返す。

  : dock_client : Control
    dlag される control

  : pos : Point

  : rect : Rect
    #dock_client の dock 先となる長方形

  : can_dock : Boolean
    #dock_client が sender に dock できるかどうか

  %c:on_get_site_info% を記述すると，ドラッグされたオブジェクトをドッキング可能な場所があれば，それについての情報を使って %c:Phi::DragDockObject% を初期化できる。 %c:on_get_site_info% は #on_dock_drop の前に呼ばれる。 %c:on_get_site_info% は #dock_site が %c:true% の場合にのみ発生する。

: on_dock_drop(source, x, y) : nil
  control に別の control がドッキングされたときに発生します。

  : source : Phi::DragDockObject
    ドロップされるオブジェクトについての情報

  : x : Fixnum

  : y : Fixnum
    マウスポインタの座標

  %c:on_dock_drop% を記述すると， control に別の control がドッキングされたときに実行する特定の処理を指定できます。 %c:on_dock_drop% は， #dock_site が %c:true% の場合にのみ発生することがあります。


: on_dock_over(accept, source, x, y, state) : arg1
  control の上に別の control がドラッグされたときに発生します。

  : accept : Boolean
    control がドッキング用にドラッグされたオブジェクトを受け付けるかどうか
  : source : Phi::DragDockObject
    ドラッグされるオブジェクトについての情報

  : x : Fixnum

  : y : Fixnum
    マウスポインタの座標

  : state : DragState
    現在のドラッグ状態

  %c:on_dock_over% を記述すると，ウィンドウ control の上にドラッグされたドッキング可能な control が， dock_client として受け入れられるかどうかを指定できます。 %c:on_dock_over% は， #on_get_site_info によって %v:source% が初期化された後で発生します。 %c:on_dock_over% は #dock_site が %c:true% の場合にのみ発生します。

: on_key_down(key, shift) : arg1
  control に focus がある間に任意のキーを押すと呼ばれる。

  すべてのキーに反応するわけではなく、on_key_press にしか反応しないキーや on_key_press には反応せずに on_key_down にしか反応しないキーもあります。一般に文字キー、ret キー、ｘｘキーは on_key_press で対応し、それ以外のファンクションキー（矢印キー）などは on_key_down で対応します。何が反応するかについてはそれぞれのイベントハンドラを仮に作成して p key を書いてみれば分かりますので、あらかじめ調べておいてください。

  : key : Fixnum
    キーボード上のキー

    英数字キー以外は仮想キーコードを使って指定する。英数字キーは「?A」「?1」のように記述します。英字は大文字でなければなりません。仮想キーコードは Win::VK_ で始まる定数として定義されています。
    Win::VirtualKeyCode#

  : 例 1
    仮想キーコードを列挙する。
--code
Ruby -r phi -e "puts Win.constants.select{|i| /^VK_/ =~ i}.sort"
--
  : 例 2
--ruby
require "phi" ; include Phi
form = Form.new
form.on_key_down = proc{|sender,key,shift|
  case key
    when ?A             ;   p "hit '?A'"
    when Win::VK_ESCAPE ;   p "hit 'VK_ESCAPE'"
    when Win::VK_F5     ;   p "hit 'VK_F5'"
    when Win::VK_TAB    ;   p "hit 'VK_TAB'"    ## not feel
    when Win::VK_PRINT  ;   p "hit 'VK_PRINT'"  ## not feel
  else                  ;   p "hit '%d'" % [key]
  end
}
form.show ; mainloop
--

  : shift : ShiftState
    [ Shift ], [ Alt ], [ Ctrl ], mouse button の状態。SS_SHIFT, SS_ALT, SS_CTRL で判断します。

  : arg1 : == key : Fixnum
    引数の key を変更した値を返します。0 を返した場合にはキー入力を無効にします。変更の有無に関わらず必ず key の値を返してください。

  : 例 1
    メソッド定義での記述によるキー入力の無効化
--ruby
require "phi" ; include Phi
form = Form.new :form, "[→]キーを無効にします"
edit1 = Edit.new form, :edit , "test1"
def edit1.on_key_down( key, shift )
  if key == 39
    print "[→]キーを無効にしました\n"
    key = 0
  end
  return key  ## 必ず key を返す必要があります。
end
form.show ; mainloop
--
  : 例 2
    手続きブロックでの記述によるキー入力の無効化
--ruby
require "phi" ; include Phi
form = Form.new :form, "[→]キーを無効にします"
edit1 = Edit.new form, :edit , "test1"
edit1.on_key_down = proc { |sender, key, shift|
  if key == 39
    print "[→]キーを無効にしました\n"
    key = 0
  end
  key	## ブロックの最後で key を評価する形で返します。
}
form.show ; mainloop
--

: on_key_up(key, shift) : arg1
  押したキーから指を離したときに呼ばれる。

: on_key_press(key) : arg1
  ASCII キーを押したときに呼ばれる。

  : key : Fixnum
    押されたキーの Char 値

  ASCII でないキー ( [ Shift ], [ F1 ] など ) は key_press event を生成しない。

  キーの組み合わせは key_press event を 1 つだけ生成する。例えば， [ Shift ] + [ A ] を押すと， [ CapsLock ] がオフならば %v:key% は %c:?A% の値となる。

  ASCII でないキーまたはキーの組み合わせに応答したい場合は， #on_key_down あるいは #on_key_up を使う。
