Microsoft Access2003

Page 11 (2005/01)

ビジュアルなお遊びフォーム
またまた気まぐれでお遊びのフォームを作ってみました。
何の役にも立ちません(。。;)ゞ

フォームにコマンドボタンを一個置くだけです。中に手頃なピットマップを入れておくといいかも。
このボタンのクリックイベントに下のコードを割り付けます。
ボタンはフォームの中央近辺置き、拡大します。

ボタンをクリックすると、このボタンがサイズを変えて移動します。フォームの左上に移動したあと、フォームの周囲をぐるぐると回りながらサイズが大きくなって行きます。
ボタンがフォームの大きさになると、自動的にフォームを閉じます。

マシンの処理速度によってボタンが動く速度は変わります。
それから、このフォームは編集後にオープンすると正しく動きません。
データベースウィンドウからオープンしてください。
Option Compare Database
Option Explicit
Private Sub cmd0_Click()
  Dim lngCounter As Long, lngW As Long, lngH As Long
  While cmd0.Top > 1
    cmd0.Top = cmd0.Top - 1
    Me.Repaint
  Wend
  While cmd0.Height > 567
    cmd0.Height = cmd0.Height - 1
    Me.Repaint
  Wend
  While cmd0.Width > 567
    cmd0.Width = cmd0.Width - 1
    Me.Repaint
  Wend
  While cmd0.Left > 1
    cmd0.Left = cmd0.Left - 1
    Me.Repaint
  Wend
  While cmd0.Width < Form.InsideHeight 'Me.Width
    Me.詳細.BackColor = RGB(Rnd * 256, Rnd * 256, Rnd * 256)
    lngW = Me.Width - cmd0.Width
    lngH = Me.InsideHeight - cmd0.Height
    For lngCounter = 0 To lngW Step 10
      cmd0.Left = lngCounter
      Me.Repaint
    Next
    For lngCounter = 0 To lngH Step 10
      cmd0.Top = lngCounter
      Me.Repaint
    Next
    For lngCounter = lngW To 0 Step -10
      cmd0.Left = lngCounter
      Me.Repaint
    Next
    For lngCounter = lngH To 0 Step -10
      cmd0.Top = lngCounter
      Me.Repaint
    Next
    cmd0.Width = cmd0.Width * 1.5
    cmd0.Height = cmd0.Height * 1.5
  Wend
  Beep
  DoCmd.Close
End Sub
[OnDirty/ダーティ時]プロパティDirtyイベントDirtyプロパティ
フォームやテキストボックスのプロパティ・シートのなかに見かける「ダーティ時」というプロパティ。Access97には無かったもの。
あまに気にとめてなかったのですけど、ちょっと調べてみました。よく分からないところもありますが、なるほど、いままで無かったのが不思議納得できるところもあります。

まず、このプロパティ、フォーム、テキストボックス、コンボボックスで連結されたものにしか現れない。非連結のテキストボックスには無いというところが大きなポイント。データが変更されたときに発生する。
似たようなプロパティ/イベントではChangeというのがありましたが、これはキーストロークごとに発生するのが特徴で、Dirtyはデータへの変更がなされるときに1回だけ発生する。
例えば最初の一文字を入力すると発生するが、二文字目からはChangeだけが発生します。DirtyイベントはChangeイベントの前に発生します。
ちなみに、OnDirtyプロパティが持つ値はテキスト型で、イベント プロシージャを設定した場合は[Event Procedure]という文字列です。
マクロを割り当てた場合はマクロ名、式ビルダの場合は式そのものです。
テキストボックスの値を変更した場合、まずフォームのDirtyイベントが発生し、次に値を変更したコントロールのDirtyイベントが発生します。
Dirtyイベントはキャンセルできます。

ややこしいことに、Dirtyプロパティというのもあって、これはフォームとリポートにのみ付属するプロパティで、変更されたかどうかをTrue/Falseで返します。もちろんデフォルトはFalseです。
適当なサンプルテーブルを作って、そのフィールドのひとつをテキストボックスに連結表示します。
下のコードはAccessのヘルプのなかの使用例を組み合せたものですが、不可解な部分があります。UndoEditsの部分ですけど・・・Me.Dirtyプロパティって変更されたコントロールを抜け出したときに初めて値が入るみたいなので、このような使い方では正しい動き方はしませんね。
不完全なコードですけど、Undoボタンの使用可、不可を制御する部分を改良してゆくと、Dirtyイベントの機能が分かってきます。
Option Compare Database
Option Explicit
Private Sub Form_Dirty(Cancel As Integer)
  Dim intYN As Integer
  intYN = MsgBox("Sub Form_Dirty " & Me.OnDirty, vbYesNo)
  If intYN = vbNo Then
    Cancel = True
  End If
End Sub

Private Sub 題名_AfterUpdate()
  UndoEdits
End Sub

Private Sub 題名_Change()
  MsgBox "Sub 題名_Change"
End Sub

Private Sub 題名_Dirty(Cancel As Integer)
  Dim intYN As Integer
  intYN = MsgBox("Sub 題名_Dirty " & Me.OnDirty, vbYesNo)
  If intYN = vbNo Then
    Cancel = True
  End If
End Sub
Sub cmdUndo_Click()
  Dim ctlC As Control
    ' 各コントロールに対して、
    For Each ctlC In Me.Controls
      If ctlC.ControlType = acTextBox Then
        ' 元の値を復元します。
        ctlC.Value = ctlC.OldValue
      End If
    Next ctlC
End Sub

Sub UndoEdits()
  If Me.Dirty Then
    Me!cmdUndo.Enabled = True  ' ボタンを使用可能にします。
  Else
    Me!cmdUndo.Enabled = False  ' ボタンを使用不能にします。
  End If
End Sub
コントロールの値の変更を判断するDirtyイベントは使い道がありそうに感じます。
上のサンプルでも使われていますが、値の変更を元に戻すために変更前の値を補損しているOldValueプロパティと組み合せて使うのがパターンになるようです。あくまで連結フォームでの話ですが。
[OnUndo/取消し時]/ Undoイベント Undoメソッド
連結フォームで変更した値を元に戻すイベントです。
レコードを移動する前なら Me.Undo だけで変更前の状態に戻せます。
コマンドバーの「戻す」ボタンやESCキーなどでUndoイベントが発生します。

ふたつのフィールドの値を変更して、あれこれやってみると機能が分かります。
Option Compare Database
Option Explicit
Private Sub cmdUndo_Click()
  Me.Undo 'Undoメソッド
End Sub

Private Sub Form_Undo(Cancel As Integer) 'フォームのUndoイベント・プロシージャ
  Dim intResponse As Integer
  Dim strPrompt As String
  strPrompt = " Form_Undo 変更を元に戻しますか?"
  intResponse = MsgBox(strPrompt, vbYesNo)
  If intResponse = vbYes Then
    Cancel = False
  Else
    Cancel = True
  End If
End Sub

Private Sub フィールド1_BeforeUpdate(Cancel As Integer)
  Dim intYN As Integer
  intYN = MsgBox("BeforeUpdate フィールド1の変更をやり直しますか?", vbYesNo)
  If intYN = vbYes Then
    Cancel = True
    Me!フィールド1.Undo 'Undoメソッドをコントロールで使う
  End If
End Sub
TimerIntervalプロパティ、Timerイベント
ほとんど使ったことがないイベントですが、一定時間経過すると発生するイベントです。
デフォルトではTimerIntervalプロパティは0になっているので発生しませんが、ここに時間をミリ秒単位で指定するとイベントが発生します。
Option Compare Database
Option Explicit
Private Sub Form_Open(Cancel As Integer)
  Me.TimerInterval = 500     '500ミリ秒=0.5秒
End Sub
Private Sub Form_Timer()
  Static intOnOff As Integer  'Timeイベントへ入るたびに値の判断をするのでStaticでないとダメ
  'Static intOnOff As Boolean  'こちらでも良い
  If intOnOff Then       '数値型変数だけど値は0/-1のBoolean型
    Me!ラベル0.Caption = ""
    Me!ラベル1.Caption = "点滅"
  Else
    Me!ラベル0.Caption = "ブリンク"
    Me!ラベル1.Caption = ""
  End If
  intOnOff = Not intOnOff     '0と-1を反転させる処理
End Sub


Page Topへ戻る