ロゴ(青) Excel/VBA Tips ロゴ(緑)

Tips03: [Exit]を通らないで外へ?  

ここに載せたのは、私がエクセルファンクラブ/モーグ等で何度か回答した内容です。


こんな経験をした事ありませんか?
      [Frame ]コントロールの中に[TextBox ]コントロールを入れていると
      [Exit ]イベントの処理を通らなくなる場合がある

実は、これは、完璧にExcelのバグです。
(注) ここでは例として[TextBox]に関して説明していますが、他のコントロールでも同様です。

[Exit ]イベントを通らなくなるケースというのは[ Frame 内から、Frame の外へ出て行く時 ]に限定
されます。具体的な操作のタイミングとしては、Frame 内の最後(タブオーダー)の[TextBox]でデータ
入力して、Enter/Tabを押す時というのが一番、目に付き易いですね。

もう少し、正確に言うと
    フレーム内からフレーム外へフォーカスを移動させた時に、移動元(フレーム内)コントロール
    のExitイベントが正規のタイミングで発生しない。
という症状です。ですから何も【最後】に限定したものではありません。「Shift+Tab」でフォーカス移動
している時は『タブオーダー先頭』のコントロールで、この症状が出ますし、マウスクリックでフレーム外へ
フォーカスを移した時は、タブオーダーに関係なく移動元のコントロールで、この症状が出ます。

この発生しなかったExitイベントは、下記のタイミングの何れかになった時に遅れて発生します。
  (1) フォームUnLoad時に[Terminate]の直前
  (2) 再び、そのFrame 内のコントロールにフォーカスが移る時に、
      Frame の[Enter]の後で、その移動してきたコントロールの[Enter]の直前
  (3) 但し、同じコントロールに戻って来た時は発生しない(Enterも発生しない)

この障害に対処するには
    テキストボックス等、Exitイベントを利用するコントロールはフレーム内には配置しない
というのが、唯一の対策です。ただし、Exitイベントを使わない【表示専用のTextBox 】なら、Frame 内に
配置しても問題ないです。

どうしても枠でグループ分けしたい時は、Label で『窪んだ横線』を作ってフォームの上下で分けるよう
にしましょう。
  Label で窪んだ横線: [SpecialEffect = fmSpecialEffectSunken] & [Height = 2]
もしくは、大きなラベル(背景透過/枠線あり/キャプションなし)を用意して、その上にTextBox を配置
するという方法でも、見た目上、フレームを使っているようなグループ分けに出来ます。
  背景透過:[BackStyle = fmBackStyleTransparent ]
  枠線あり  :[SpecialEffect = fmSpecialEffectEtched
  ※ TextBox 等がラベルの下になって隠れてしまう場合は、ラベルを選択して、
      メニューから[書式→順序→最背面へ移動]とします


Video Capture ( Tips03_FrameFocus.mp4   0.6MB )

下記の UserForm でもう一度詳しく症状を説明しますね。
    [TextBox1]
    +--------------- Frame1 -----------------------------+
    I  [TextBox2]  [TextBox3]  [Textbox4]  [Textbox5]    I
    +----------------------------------------------------+
    [TextBox6]

    UserFormタブオーダー : TextBox1 → Frame1 → TextBox6
    Frame1内タブオーダー : TextBox2 → TextBox3 → TextBox4 → TextBox5

【フレームの内から外へタブ移動】
  Tab で[TextBox5 → TextBox6] または、Shift +Tab で[TextBox2 → TextBox1] のフォーカス
  移動を行なった場合、TextBox5(またはTextBox2)の『Exitイベント』は以下のいずれかのタイミング
  になった時に始めて発生する。
      (1) UserForm が【Unload】される直前(QueryCloseの後で、Terminateの前)
      (2) 再び Frame1内にフォーカスが移る(ただし他のコントロール)時に、Frame1のEnterイベント
          発生後で、フォーカスが移るコントロールのEnterイベント発生前

    TextBox5 → TextBox6 → TextBox1 → TextBox2 のフォーカス移動の場合は

      Box5_Enter → [無い!] → Frame1_Exit → Box6_Enter → Box6_Exit → 
          Box1_Enter → Box1_Exit → Frame1_Enter → Box5_Exit → Box2_Enter

【フレームの内と外を交互にタブ移動】
  TabShift +Tab で[TextBox2 ←→ TextBox1] または [TextBox5 ←→ TextBox6] のフォーカス
  移動を交互に行なうと、何回やっても TextBox2(またはTextBox5)のEnter/Exitイベントは発生しない。

    TextBox5 → TextBox6 → TextBox5 → TextBox6 → TextBox5 → TextBox6 のフォーカス移動
    場合は

      Box5_Enter → Frame1_Exit → Box6_Enter → Box6_Exit → Frame1_Enter →
          Frame1_Exit → Box6_Enter → Box6_Exit → Frame1_Enter → Frame1_Exit → Box6_Enter

【 想定原因 】
   a) 「今どのコントロールにフォーカスがあるのか」という情報が、ユーザーフォームと個々のフレームで独立して保持されている(タブオーダーが独立して割り当てられているので、当然といえば当然ですね)。
 
   b) フレームに対して「内→外」・「外→内」といったフォーカス移動は、フレーム内部の空間から見た時、
      [フレーム内の他のコントロール]に移ったという通知がないから、
      フォーカスは
未だ今のコントロール上にある
と捉えて、フレーム内のフォーカス情報をリセットしていないのではないか。
 
   c) つまり、
    TextBox5(内) → TextBox6(外) → TextBox1(外) → TextBox2(内)
というフォーカス移動も、フレーム内部から見ると
    TextBox5(内) → TextBox2(内)
という、たった1回のフォーカス移動としてしか認識されておらず、間に他のコントロールが割り込んでいることを知らないのでしょう。結果として、正しく(?) [Box2_Enter]の【直前】で[Box5_Exit] を発生させた為
    Box5_Enter → [→→→→→→] → Box5_Exit=>Box2_Enter
                                 ↓(この位置に下記のイベントが入る)
          [ → Frame1_Exit → Box6_Enter ・・・ → Frame1_Enter → ]
という、外から見ると奇妙なタイミングで[Box5_Exit]が発生したものと思われます。

「Unload 直前まで[Exit]が発生しない」「内/外を交互に移動するとEnter/Exit ともに発生しない」という件も、同じ理由で理解できます。つまり、
    『フレーム内の今のコントロールから全く移動していない
と認識しているのでしょう。
 


フレーム絡みでは、もうひとつバグがあります。

フレーム外から、フレーム内のコントロールにマウスクリックでフォーカス移動し、その移動先コント
ロールが『フレーム内タブオーダー先頭』以外のコントロールだった場合、移動先コントロールの
Enterイベントが発生する前に、『フレーム内タブオーダー先頭』コントロールのEnter/Exitイベント
が連続して発生します。

【マウスクリックでフレームの外から 内へフォーカス移動】
    マウスクリックでフレームの外から内(タブオーダー0番以外)へフォーカス移動すると、
    移動先コントロールのEnterイベント発生前に、【タブオーダー0番のコントロール】のEnter
    /Exitが続けて発生する。

    TextBox1 −クリック→ TextBox4 の場合は

    Box1_Exit → Frame1_Enter → Box2_Enter → Box2_Exit → Box4_Enter


尚、これらの障害は、Frame コントロールだけでなく、MultiPage コントロールでも発生します。

この症状の検証ブック「イベント発生順序検証ツール解説)」

 Home   Back Page   Next Page

ロゴ(ゴールド)   ロゴ(ゴールド)

角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2001 Allrights Reserved.