サブクラスでパワーアップ!!
VB5で登場した AddressOf により実現したこの機能!!
市販ツールを買わなくてもいろんな事が出来るようになる!!(と、思う(^^;))
サンプルではテキストボックスを使って、数値のみの入力が出来るようにする。
ただし、複数のテキストボックスに対応するためには改良が必要。
(デフォルトのウィンドウプロシージャのアドレスを1つしか持っていないため。)
'[basSubClass.bas]
' テキストボックスを数値のみの入力にする。
' Ver1.0
' Programinged By Uz.
Option Explicit
'-- API定数群
Public Const GWL_WNDPROC = (-4)
Public Const WM_CHAR = &H102
'-- API関数群
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
ByVal hWnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long _
) As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" ( _
ByVal lpPrevWndFunc As Long, _
ByVal hWnd As Long, _
ByVal Msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long _
) As Long
'-- プライベート変数群
Private lpDefaultProc As Long 'デフォルトのウィンドウプロシージャのアドレス
'-- パブリック関数群
'サブクラス化開始関数
Public Function SubClass(hWnd As Long) As Boolean
On Error GoTo ErrorHandle
'デフォルトのウィンドウプロシージャのアドレスの保存と新しいウィンドウプロシージャの登録
lpDefaultProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
If lpDefaultProc = 0 Then GoTo ErrorHandle
SubClass = True
Exit Function
ErrorHandle:
SubClass = False
End Function
'サブクラス化終了関数
Public Function UnSubClass(hWnd As Long) As Boolean
Dim lpX As Long '戻り値を格納
On Error GoTo ErrorHandle
'サブクラス化していないときは処理を行わない
If lpDefaultProc <> 0 Then
'ウィンドウプロシージャをデフォルトに戻す
lpX = SetWindowLong(hWnd, GWL_WNDPROC, lpDefaultProc)
If lpX = 0 Then GoTo ErrorHandle
lpDefaultProc = 0
End If
UnSubClass = True
Exit Function
ErrorHandle:
UnSubClass = False
End Function
'自前のウィンドウプロシージャ
Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
'Debug.Print Hex(hWnd), Hex(uMsg), Hex(wParam), Hex(lParam) 'すべてのメッセージを表示(結構楽しい(^_^))
Select Case uMsg
Case WM_CHAR '文字が送られたら
Select Case wParam '送られた文字
Case Asc("0") To Asc("9"), vbKeyReturn, vbKeyBack, vbKeyHome, vbKeyEnd
'許可する文字なら何もしない
Case Else
'送られた文字を無効化する
wParam = 0
End Select
End Select
'デフォルトのウィンドウプロシージャを呼び出す
WindowProc = CallWindowProc(lpDefaultProc, hWnd, uMsg, wParam, lParam)
End Function
'[frmMain]
' フォーム側はこれだけ(^^)
'
Option Explicit
'終了ボタン
Private Sub cmdExit_Click()
Call Unload(Me)
End Sub
'フォームロード
Private Sub Form_Load()
'サブクラス化開始
Call SubClass(txtTextBox.hWnd)
End Sub
'フォームアンロード
Private Sub Form_Unload(Cancel As Integer)
'サブクラス化終了
Call UnSubClass(txtTextBox.hWnd)
End Sub
サンプル subclass.lzh