|
▼年寄り さん:
おはようございます。
>>質問1
>>UserFormに直接貼り付けたTextBoxコントロールのイベントと、Classモジュールで今回作成したf_txtというTextbox(Msforms.Textbox)のイベントに違いがあります。Textbox(Msforms.Textbox)のイベントの方が少ない。何故ですか?
>はい、おっしゃるとおりです。
>特にEnter、Exit、Update(Before,After)とありませんよね?
>本当の理由は私もわかりませんが、風の噂ではコンパイラー言語VBとの
>格差だとか・・・。
>これがあるので私は、Keydownというイベントにてデータチェックを行っている
>場合が多いのですが・・・。
>
>UserformのプロパティにActivecontrolというプロパティがあります。
>このプロパティでアクティブになっている(フォーカスを持っている)コントロールが
>取得できます。このプロパティの中身を監視して変化があったらイベントを発生させる
>という手法が考えられますし、私もだいぶ前にそんなコードを見たことがあります。
>(Excel2000からは、独自のイベントが作成できますからね)
>
>汎用的に作るには、時間かかるかなあ・・(実用的か否かの検証も大変そう)。
汎用的ではありません。
アルゴリズムとしてこのようにすればよいのではないかという
例題です。
このトピックで取り上げてきたマルチページにテキストボックス
を実行時作成するコードを例題にします。
汎用的ではありません。
アルゴリズムとしてこのようにすればよいのではないかという
例題です(汎用的にするにはさらなる検証が必要です)
繰り返しになってしいますが、再度コードを全部掲載します。
新規ブックにはコントロールのないユーザーフォーム(Userform2)を作成してください。
まず、クラスモジュール
Class1には、
'====================================
Public WithEvents txt As MSForms.TextBox
Public id As Long
'======================================================================
Private Sub txt_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 13 Or KeyCode = 9 Then
If Not IsNumeric(txt.Text) Then
MsgBox "数字を指定して!!"
KeyCode = 0
End If
End If
End Sub
'↑これは、以前にも掲載したコードです
次に追加でClass2を作成し当該モジュールに
'========================================================
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public 監視 As Boolean
Public p_obj As Object
'========================================
Sub kanshi()
Dim svctrl As MSForms.Control
Dim nctrl As MSForms.Control
Dim ss As MSForms.MultiPage
Set svctrl = p_obj.ActiveControl
If UCase(TypeName(svctrl)) = UCase("multipage") Then
Set p_obj = svctrl.SelectedItem
Set svctrl = p_obj.ActiveControl
End If
監視 = True
Do While 監視 = True
Set nctrl = p_obj.ActiveControl
If nctrl Is Nothing Then
Exit Do
End If
If svctrl.Name <> nctrl.Name Then
Call act_event(svctrl, nctrl)
Set svctrl = nctrl
If UCase(TypeName(svctrl)) = UCase("multipage") Then
Set p_obj = svctrl.SelectedItem
Set svctrl = p_obj.ActiveControl
End If
svctrl.SetFocus
End If
Sleep (100)
DoEvents
Loop
Set svctrl = Nothing
End Sub
'====================================================
Sub kaijo()
監視 = False
End Sub
'=====================================================
Private Sub Class_Terminate()
kaijo
DoEvents
Set p_obj = Nothing
End Sub
'=======================================================================
Private Sub act_event(f_ctrl As MSForms.Control, n_ctrl As MSForms.Control)
'ここにコントロールが変わったときに行うコードを書きます
If Not IsNumeric(f_ctrl.Value) Then
MsgBox "駄目駄目数字入れてくれきゃ"
Set n_ctrl = f_ctrl
End If
End Sub
Userform2では、
'=====================================================
Dim c_txt(1 To 20) As Class1
Dim c_eve As Class2
'=====================================================
Private Sub UserForm_Activate()
c_eve.kanshi
End Sub
'======================================================
Private Sub UserForm_Deactivate()
c_eve.kaijo
End Sub
'===========================================================
Private Sub UserForm_Initialize()
Dim p As Page
Dim sz As Double
Dim wk As String
Dim idx As Long
With Me
.Height = 300
.Width = 420
End With
With Controls.Add("Forms.MultiPage.1", "mltp")
'↑マルチページに名前を付けます
.Top = 75
.Left = 5
.Height = 200
.Width = (9.75 * 40 + 12) + 0.75
.Pages.Remove 1
With .Font
.Name = "MS ゴシック"
.Size = 10
sz = Int(.Size / 0.75) * 0.75
End With
Set p = .Pages(0)
p.Caption = String(Int((Int(.Width / 0.75) * 0.75 - 12.75) / sz), " ")
wk = p.Caption
Mid(wk, 1, 9) = "マルチページ使用例"
p.Caption = wk
p.ScrollBars = 2
p.ScrollHeight = 1000
For idx = 1 To 20
Set c_txt(idx) = New Class1
With c_txt(idx)
.id = idx
Set .txt = p.Controls.Add("Forms.TextBox.1")
With .txt
.Top = (idx - 1) * 50 + 20
.Left = 30
End With
End With
Next
End With
Set c_eve = New Class2
Set c_eve.p_obj = Me
End Sub
'=============================================================
Property Get f_txt(id As Long) As MSForms.TextBox
Set f_txt = c_txt(id).txt
End Property
'================================================================
Private Sub UserForm_Terminate()
Set c_eve = Nothing
Erase c_txt() 'フォームでの作業終了時に配列を初期化するコードも追加
End Sub
で標準モジュールに
'=============================================
Sub main()
UserForm2.Show
End Sub
でれで、Mainを実行してみてください。
テキストボックスに数字以外を入力してEnterキーを押した場合は、
今までどおり"数字を指定して!!"と表示されます。
テキストボックスに数字以外を入力してマウスで別コントロールに移動してください
Class2に記述された"駄目駄目数字入れてくれきゃ"が表示されます。
実際には、これを汎用的なクラスにし、イベントもUserform2の中で
記述できるようにしなければなりません。
「駆使すれば出来るかもしれない」という例題として
確認してください。
|
|