パソコン活用研究5番街(Visual Basic、Excel(VBA)、BASIC プログラミング研究)


FROMのイベント その1
(プログラム起動時、終了時、再描画時のイベント)

                 
オブジェクトとイベントのところでもFORMのイベントについて触れましたが、今回は特にVisual Basicの起動時
と終了時および再描画時のイベントについて少し探求して見たいと思います。

1 起動時と終了時のイベント
まず、プログラム起動時、終了時にFORMにどんなイベントがどんな順番で発生するか見てみたいと思います。
これがわかれば、どのイベントにどういうコードを記述したらいいのかはっきりと理解できるようになるでしょう。

以下のように、シンプルなFORMを用意して、イベントが発生するとメッセージボックスを表示するような
プログラムを作ってみましょう。

(図1)

Event Test
VERSION 4.00
Begin VB.Form Form1 
   Caption         =   "Event_Test"
   ClientHeight    =   555
   ClientLeft      =   9660
   ClientTop       =   4860
   ClientWidth     =   2160
   Height          =   1065
   Left            =   9600
   LinkTopic       =   "Form1"
   ScaleHeight     =   555
   ScaleWidth      =   2160
   Top             =   4410
   Width           =   2280
End
Attribute VB_Name = "Form1"
Attribute VB_Creatable = False
Attribute VB_Exposed = False

Private Sub Form_Click()
Circle (500, 200), 200
End Sub

Private Sub Form_Initialize()
MsgBox "Initialize"
End Sub


Private Sub Form_Load()
MsgBox "Load"
End Sub


Private Sub Form_Paint()
MsgBox "Paint"
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
MsgBox "QueryUnload"
End Sub


Private Sub Form_Resize()
MsgBox "Resize"
End Sub

Private Sub Form_Terminate()
MsgBox "Terminate"
End Sub


Private Sub Form_Unload(Cancel As Integer)
MsgBox "Unload"
End Sub


このプログラムを起動すると
Initialize --> Load --> Resize -->Paint
の順にイベントが発生することがわかります。

もっと詳しく書くとと
プログラムがメモリに読み込まれる(インスタンス生成) --> Initializeイベント -->
Loadイベント -->
FORMの表示 --> Resizeイベント --> Paintイベント
となります。

ではFORM右上の_ボタンを押してアイコン化してみて下さい。そうするとResizeイベントが発生するはずです。
アイコン化したプログラムをクリックして元の大きさに戻すとResize --> Paintという順にイベントが発生
します。

では×ボタンを押して、このプログラムを終了して下さい。
QueryUnLoad --> Unload -->Terminate
という順にイベントが発生するはずです。

InitializeとLoadイベントはプログラム起動時に1回しか発生しません。従って、初期設定など、最初に1度だけ
記述すれば良いコードは、InitializeかLoadイベントに記述します。

FORMのサイズが変更されたときには、Resizeイベントが、再描画された時にはPaintイベントが発生します。
このイベントに書くべきコードについては、後でじっくり研究してみましょう。

QueryUnloadはプログラム終了の直前に発生するイベントです。プログラム終了前に処理すべき事項に関する
コードを記述するのが一般的です。
例えば、「本当に終了しますか」、「変更されたファイルを保存しますか」という確認ダイアログを表示させたり、
場合によっては、ここで終了をキャンセルしたりします。
引数Cancelの値を0以外に変更すると、プログラム終了の動作(アンロード)はキャンセルされます。

UnloadイベントはQueryUnloadに引き続き発生します。Unloadにおいても、引数Canselを0以外に変更すると
FORMのアンロードはキャンセルされます。
Terminateイベントは、オブジェクトの参照がメモリーから解放された時に発生します。
Unload,Terminateは基本的にプログラム終了時に1回しか発生しませんので、プログラム終了時に1度だけ
行えばいい処理はここに記述します。
Terminateイベントが終了すると、プログラムはメモリから解放されて、消えます。

2 描画時のイベント
Resize,Paintイベントについて、上でも軽く触れましたが、もう少しじっくりみてみましょう。
上記のEvent Testで、Formをアイコン化したり、最大化したり、元の大きさに戻したりして見てください。
アイコン化した時には、Resizeイベントが発生し、アイコン状態から元のサイズに戻すと、Resize --> Paint の
順でイベントが発生することがわかると思います。
また、他のWindowの下に隠してから、そのWindowをどかしてEvent Testを再表示してみて下さい。
今度は、Paintイベントだけが発生するはずです。

すなわち、
Resizeイベントは、Formのサイズが変更された時に発生
Paintは画面の表示が変更された時に発生
ということです。

以上で基本は完了です。では、もう少しPaintイベントに関連するテクニックについて研究してみましょう。
(これ以降は、Visual Basic専用の事項となります)
上記のEvent TestのFORMをクリックして下さい。FORM上に○が描画されます。
このFORMの一部に別のアプリケーションを重ねてから、移動してみて下さい。隠れていた部分は消えてしまい
再描画されません。(図2を参照)
このようにグラフィックメソッド(*)によって描かれた図形、文字は別のWindowに隠れた部分は、再び表示され
た時に、再描画されず消えてしまいます。
(*) グラフィックメソッド
Circle, Cls, Line, PaintPicture, Point, PSet, Printなど。

  (図2)


隠れていた部分が再描画されないと困る場合、再描画するにはどうしたらいでしょうか。手としては2つの
方法があります。

(A) Paintイベントにグラッフィックメソッドを記述する。
例えば、Event Testのコードを以下のように変更して実験してみて下さい。
変更のある部分だけのせておきます。

VERSION 4.00
Begin VB.Form Form1 
   Caption         =   "Event_Test"
   ClientHeight    =   555
   ClientLeft      =   9660
   ClientTop       =   4860
   ClientWidth     =   2160
   Height          =   1065
   Left            =   9600
   LinkTopic       =   "Form1"
   ScaleHeight     =   555
   ScaleWidth      =   2160
   Top             =   4410
   Width           =   2280
End
Attribute VB_Name = "Form1"
Attribute VB_Creatable = False
Attribute VB_Exposed = False


Private Sub Form_Paint()
MsgBox "Paint"
Circle (500, 200), 200
End Sub

Private Sub Form_Click()
' 以下の行はコメントにする
'Circle (500, 200), 200 
End Sub


こうすると、再描画(Paintイベント発生)のたびに、グラッフィックメソッドが実行されますので、問題解決です。
実験してみて下さい。

(B) FORMのAutoRedrawプロパティをTrueにする。
AutoRedrawプロパティはデフォルトではFalseに設定されています。このプロパティをTrueにすると、隠れて
いた部分のグラフィックも再描画されるようになります。
ただし、AutoRedrawプロパティをTrueにすると、再表示用の作業メモリを消費する上、実行スピードも落ちます。
それがいやな場合は、(A)で述べるように、Paintイベントにグラフィックメソッドを記述するという方法をとれば
いいでしょう。

Event Testを以下のように変更して実験してみて下さい。変更のあるコードだけあげておきます。

VERSION 4.00
Begin VB.Form Form1 
   AutoRedraw      =   -1  'True
   Caption         =   "Event_Test"
   ClientHeight    =   555
   ClientLeft      =   9660
   ClientTop       =   4860
   ClientWidth     =   2160
   Height          =   1065
   Left            =   9600
   LinkTopic       =   "Form1"
   ScaleHeight     =   555
   ScaleWidth      =   2160
   Top             =   4410
   Width           =   2280
End
Attribute VB_Name = "Form1"
Attribute VB_Creatable = False
Attribute VB_Exposed = False

Private Sub Form_Load()
MsgBox "Load Start"
Circle (500, 200), 200
MsgBox "Load End"
End Sub

Private Sub Form_Click()
' 以下の行はコメントにする
'Circle (500, 200), 200 
End Sub

プログラムを起動すると、以下のようにメッセージボックスが表示されます。
Initialize --> Load start --> Load End --> Resize
AutoRedrawプロパティがTrueだと、Paintイベントは発生しません。この点は要注意です。Paintイベントにコード
を記述しても実行されませんので、気をつけて下さい。

グラッフィックメソッド Circle は、Load StartとLoad Endの間で実行していますが、Loadイベントの時点では
Formが表示されていないので、当然○は描画されません(表示するためのFormが表示されてないのですから
当たり前ですよね)
Loadイベント終了後、Formが表示されると、○はしっかり描画されます。

この辺りを詳しく書くと以下のようになります。
Initializeイベント -->
Loadイベント --> (Load Start) --> (Circle実行:でも描画されない) --> Load End -->
FORMの表示(○が描画される) --> Resizeイベント

オブジェクトとイベントでも書きましたが、AutoRedrawプロパティがFalseだと、Loadイベントに記述した
グラッフィックメソッドは無効になります。上記のコードでAutoRedraw=Falseにすると、○は描画されません。


TopPage > Visual BasIc&Excel活用研究目次