Detecting (in VBA) when the window containing an excel instance becomes active

后端 未结 2 1207
不知归路
不知归路 2020-12-06 11:52

I can see the WindowActivate events firing, at various levels, when I switch between windows within excel, but is there a way to fire an event when excel become

2条回答
  •  一生所求
    2020-12-06 12:37

    I modified @AndASM 's very nice solution to work in a 64 bit environment. Changes were

    • changed API function call parameters from Long to LongLong parameters
    • included PtrSafe attributes
    • replaced Sheet1.[A1] = with range("a1").value = syntax

    @andasm's code with mods follows

    Option Explicit
    
    Private Const EVENT_SYSTEM_FOREGROUND = &H3&
    Private Const WINEVENT_OUTOFCONTEXT = 0
    
    Private Declare PtrSafe Function SetWinEventHook Lib "user32.dll" (ByVal eventMin As Long, _
    ByVal eventMax As Long, _
    ByVal hmodWinEventProc As LongLong, _
    ByVal pfnWinEventProc As LongLong, _
    ByVal idProcess As Long, _
    ByVal idThread As Long, _
    ByVal dwFlags As Long) As Long
    Private Declare PtrSafe Function GetCurrentProcessId Lib "kernel32" () As Long
    Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
    
    Private pRunningHandles As Collection
    
    Public Function StartEventHook() As Long
      If pRunningHandles Is Nothing Then Set pRunningHandles = New Collection
      StartEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, 0&, AddressOf WinEventFunc, 0, 0, WINEVENT_OUTOFCONTEXT)
      pRunningHandles.Add StartEventHook
    End Function
    
    Public Sub StopEventHook(lHook As Long)
      Dim LRet As Long
      If lHook = 0 Then Exit Sub
    
      LRet = UnhookWinEvent(lHook)
    End Sub
    
    Public Sub StartHook()
        StartEventHook
    End Sub
    
    Public Sub StopAllEventHooks()
      Dim vHook As Variant, lHook As Long
      For Each vHook In pRunningHandles
        lHook = vHook
        StopEventHook lHook
      Next vHook
    End Sub
    
    Public Function WinEventFunc(ByVal HookHandle As Long, ByVal LEvent As Long, _
                            ByVal hWnd As Long, ByVal idObject As Long, ByVal idChild As Long, _
                            ByVal idEventThread As Long, ByVal dwmsEventTime As Long) As Long
      'This function is a callback passed to the win32 api
      'We CANNOT throw an error or break. Bad things will happen.
      On Error Resume Next
      Dim thePID As Long
    
      If LEvent = EVENT_SYSTEM_FOREGROUND Then
        GetWindowThreadProcessId hWnd, thePID
        If thePID = GetCurrentProcessId Then
          Application.OnTime Now, "Event_GotFocus"
        Else
          Application.OnTime Now, "Event_LostFocus"
        End If
      End If
    
      On Error GoTo 0
    End Function
    
    Public Sub Event_GotFocus()
        Range("a1").Value = "Got Focus"
    End Sub
    
    Public Sub Event_LostFocus()
       Range("a1").Value = "Nope"
    End Sub
    

提交回复
热议问题