ダイアログでサイズを指定し、お絵かきロジックシート(らしきモノ)を作成するところまでは辿り着きました。ここではフォームの初期化を題材にして、各種イベントの利用方法について理解を深めて行きます。
フォーム表示時点で入力項目を初期化するなどの処理では、イベントプロシージャについての理解が不可欠です。「入力値が変化したとき」とか「フォームが表示されるとき」といった時点で発生するイベントについて、発生タイミングや発生時の状況などを実例で調べて行きましょう。
フォームが表示されるときにはInitializeイベントが発生します。正確に言うと「オブジェクト(この場合はフォームオブジェクト)がロードされ、表示される直前」に発生します。そこでSetFieldSizeフォームのInitializeイベントプロシージャに初期化のコードを記述すれば良いということになります。
Private Sub UserForm_Initialize()
' 編集領域設定初期化
Me.FieldWidth.Text = vbNullString '縦横サイズクリア
Me.FieldHeight.Text = vbNullString
End Sub
横サイズ入力欄であるFieldWidthとFieldHeightのTextプロパティにNull値を代入しています。テキストボックスにおいてはValueプロパティもTextプロパティと同様の値を持つので、Valueで記述しても良いのですが、使用者が文字列を入力するかも知れないという想定を明示的にするためTextでの記述としています。
vbNullStringはVB定義定数の一つで、空文字列を示します。空文字列であるNull値にはvbNullCharとvbNullStringとがあり、同じような意味でありながらこれらには相違点があります。vbNullCharはChr(0)と同値であり、ASCIIキャラクタにおけるNullです。よく文字列終端記号として使われ(以前はASCIZ文字列なんて言いましたが)、「1文字目が最終文字だということは文字列としては空ですよ」という解釈で問題ないと思います。これに対してvbNullStringは値がChr(0)であるかどうかすらも確定していない空文字列です。1文字目が0だと解るのは文字列のメモリ上での位置が確定しているからで、どこに文字列があるかも解らない場合は1文字目のゼロ判定すらできません。以下のコードを実行すると各定数が違うモノだということが分かります。
Sub Nul()
Debug.Print "" = vbNullChar
Debug.Print "" = vbNullString
Debug.Print vbNullChar = vbNullString
End Sub
VBEのイミディエイトウィンドウに表示される結果はFalse/True/Falseです。ただしヘルプによるとvbNullStringは「""」とは異なると書いてあります。上記のような比較では同一と見なされるものの、厳密には違うということでしょうか。
フォームが表示されたとき、順番として横サイズ入力欄にカーソルがある状態にしたいですよね。もちろんそのためにタブオーダーをしっかりと設定する必要があるのですが、ここではプログラム上から初期フォーカスを制御する方法について考えてみましょう。これは何も入力されていない、通常の設定フォームではタブオーダー通りで問題なくても、エラーなどの特殊な状況で、問題のないオブジェクトには初期値が設定されていて、問題が見つかったオブジェクトにフォーカスした状態にした上でフォームを表示させたいときなどに役立ちます。
オブジェクトのフォーカス設定はSetFocusメソッドで行いますが、先程のInitializeイベント内でフォーカス制御しようとしても思った通りになりません。これはInitializeイベントがアクティブになる‘直前’であり、メモリ上にはロードされているものの、まだ表示されていないタイミングだからです。表示されていないオブジェクトにフォーカスを渡そうとしても上手く行くはずはなく、SetFocusはフォームがアクティブになった段階で実行されなければなりません。具体的にはフォームのActivateイベントに以下のコードを記述します。
Private Sub UserForm_Activate()
' フォームアクティブイベント
Me.FieldWidth.SetFocus '横サイズ入力欄フォーカス
End Sub
SetFocusメソッドがInitializeイベント内でうまく働かないからとActivateイベントに記述するのなら、Textプロパティの初期化もInitializeイベントではなくActivateイベントに入れちゃえばいいのでは?と思われるかも知れませんが、初期化前の入力欄が一瞬表示され、何らかの値が入っていた場合、瞬間的に視認できてしまう恐れがあります (現在のバカっ速いPCでは無用の心配ですが)。またイベント処理を正しく記述するという観点からも、面倒かも知れませんが別々のプロシージャに分けるべきでしょう。
今まで進めてきたInitializeイベントでのTextプロパティ初期化やActivateイベントでのSetFocusメソッドの実行などは、キャンセルクリック時にオブジェクトのロード解除している現状では、実を言うと必要ありません。こう書くと「何だいらんコトしてたのか」と怒られそうですが、‘その1’で「HideメソッドではなくUnloadステートメントを使いましょう」と言ってきたことを実感できる題材だと思ったからです。
試しにInitializeイベントとActivateイベントを総てコメントアウトした状態で、キャンセルクリックイベントのUnload Meの部分をMe.Hideに変更した状態でフォームを開き、サイズ欄に任意のキーボード入力をした状態でキャンセルをクリックしてみて下さい。この状態だとフォームやそれに乗っかっているコントロールは見えないだけでまだメモリ上に存在するのですが、再度マクロ実行によりフォームを表示させると、先程の入力内容が保持されており、キャンセルボタンにフォーカスが残っていることが見て取れます。つまり上記の初期化作業はHideメソッドでフォームを非表示にするだけの場合は恐らく必須となるでしょう。キャンセルイベントをHideメソッドのままにしてInitializeイベントとActivateイベントのコメントアウトを解除すると、初期化作業の効果が解ります。
これに対してUnloadステートメントではメモリ上から完全に消去されるので、入力途中の内容も破棄されて各入力欄は空欄になり、フォーカス情報も残っていないので、タブオーダーの一番若いコントロールでカーソルが点滅する状態になるというワケです。
メモリ上に残っていれば再利用可能で、メモリから忘れ去られると始めからやり直しになるというイメージは、今後変数のスコープを理解する上でも必要になってきます。逆にいつまでもメモリ上にあれば、初期状態でスタートしたいときに初期化プログラムが必要になってくるコトは、ここでの解説で理解できますよね。
← 前へ → 次へ ▲ ページトップ