ここに載せたのは、私がエクセルファンクラブ/モーグ等で何度か回答した内容です。
こんな経験をした事ありませんか?
[Frame ]コントロールの中に[TextBox ]コントロールを入れていると
[Exit ]イベントの処理を通らなくなる場合がある。
実は、これは、完璧にExcelのバグです。
[ KB 210734 ] OFF2000: Exit Event for TextBox in a Frame Does Not Run Correctly
(注) ここでは例として[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
【フレームの内と外を交互にタブ移動】
Tab と Shift +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 コントロールでも発生します。
※ この症状の検証ブック「イベント発生順序検証ツール (解説)」
|
||
角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2001 Allrights Reserved. |