VB如何觸發焦點事件和失去焦點事件
阿新 • • 發佈:2019-01-22
VB中有一個LostFocus事件和一個GotFocus事件,看名字似乎是噹噹前視窗失去焦點或得到焦點時觸發的事件。但在實際應用時卻發現當這個視窗和Windows中其他視窗進行切換時並沒有觸發這兩個事件。現在解析一下這兩個事件。
---- Form_LostFocus、Form_GotFocus是指的是一個MDI主父窗體呼叫了多個子窗體,當這些子窗體之間切換時,就觸發這兩個事件;當一個窗體中的多個文字框,滑鼠點選另一個文字框時,也會觸發這兩個此事件,文字框在 Windows內部實際上也是一個視窗。
---- Windows內部是通過訊息來觸發事件的,這兩個事件在Windows內部對應的訊息是WM_NCACTIVATE,當該訊息的wParam為0時表示是失去焦點,為非0時表示得到焦點。在模組中:
Public Declare Function SetWindowLong Lib
"user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long,
ByVal dwNewLong As Long) As Long
Public Declare Function DefWindowProc Lib
"user32" Alias "DefWindowProcA"_
(ByVal hwnd As Long, ByVal wMsg As Long,
ByVal wParam As Integer, ByVal_
lParam As Long) As Long
Public 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
Public Const WM_NCACTIVATE = &H86
Public Const GWL_WNDPROC = (-4)
Public OldWndProc&
Public Function Hook&(ByVal hWnd1&)
OldWndProc = SetWindowLong(hWnd1,
GWL_WNDPROC, AddressOf NewWndProc)
Hook = OldWndProc
End Function
Public Sub UnHook(ByVal hWnd1&)
SetWindowLong hWnd1, GWL_WNDPROC, OldWndProc
End Sub
Public Function NewWndProc&(ByVal hWnd1&, ByVal uMsg&,
ByVal wParam&, ByVal lParam&)
If uMsg = WM_NCACTIVATE Then
If wParam = 0 Then ’失去焦點
Form1.Caption = "失去焦點"
註釋:在這裡加入在失去焦點時想要執行的程式碼
Else
Form1.Caption = "得到焦點"
’在這裡加入在得到焦點時想要執行的程式碼
End If
End If
NewWndProc = CallWindowProc(OldWndProc,
hWnd1, uMsg, wParam, lParam)
End Function
視窗中程式碼如下:
Private Sub Form_Load()
Hook Form1.hwnd
End Sub
Private Sub Form_QueryUnload(Cancel As Integer,
UnloadMode As Integer)
UnHook Form1.hwnd
End Sub
---- 注意:在編寫“失去焦點”和“得到焦點”的程式碼時,不要使用VB本身自帶的函式,如: MsgBox()和Print()等,因為這裡不支援,要用MessageBox()、TextOut()等API函式來代替,否則VB會出現“非法保護性錯誤”而把VB連帶程式一起關掉。
---- Form_LostFocus、Form_GotFocus是指的是一個MDI主父窗體呼叫了多個子窗體,當這些子窗體之間切換時,就觸發這兩個事件;當一個窗體中的多個文字框,滑鼠點選另一個文字框時,也會觸發這兩個此事件,文字框在 Windows內部實際上也是一個視窗。
---- Windows內部是通過訊息來觸發事件的,這兩個事件在Windows內部對應的訊息是WM_NCACTIVATE,當該訊息的wParam為0時表示是失去焦點,為非0時表示得到焦點。在模組中:
Public Declare Function SetWindowLong Lib
"user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long,
ByVal dwNewLong As Long) As Long
Public Declare Function DefWindowProc Lib
"user32" Alias "DefWindowProcA"_
(ByVal hwnd As Long, ByVal wMsg As Long,
ByVal wParam As Integer, ByVal_
lParam As Long) As Long
Public 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
Public Const WM_NCACTIVATE = &H86
Public Const GWL_WNDPROC = (-4)
Public OldWndProc&
Public Function Hook&(ByVal hWnd1&)
OldWndProc = SetWindowLong(hWnd1,
GWL_WNDPROC, AddressOf NewWndProc)
Hook = OldWndProc
End Function
Public Sub UnHook(ByVal hWnd1&)
SetWindowLong hWnd1, GWL_WNDPROC, OldWndProc
End Sub
Public Function NewWndProc&(ByVal hWnd1&, ByVal uMsg&,
ByVal wParam&, ByVal lParam&)
If uMsg = WM_NCACTIVATE Then
If wParam = 0 Then ’失去焦點
Form1.Caption = "失去焦點"
註釋:在這裡加入在失去焦點時想要執行的程式碼
Else
Form1.Caption = "得到焦點"
’在這裡加入在得到焦點時想要執行的程式碼
End If
End If
NewWndProc = CallWindowProc(OldWndProc,
hWnd1, uMsg, wParam, lParam)
End Function
視窗中程式碼如下:
Private Sub Form_Load()
Hook Form1.hwnd
End Sub
Private Sub Form_QueryUnload(Cancel As Integer,
UnloadMode As Integer)
UnHook Form1.hwnd
End Sub
---- 注意:在編寫“失去焦點”和“得到焦點”的程式碼時,不要使用VB本身自帶的函式,如: MsgBox()和Print()等,因為這裡不支援,要用MessageBox()、TextOut()等API函式來代替,否則VB會出現“非法保護性錯誤”而把VB連帶程式一起關掉。