Ach, ich war gerade eh dabei:
Du kannst eine eigene Klasse ApplicationWindow schreiben, die über den Handle der Application überwacht, ob die Excel-Application aktiviert wurde. Hierzu benötigst du zunächst einmal einen API-Aufruf von GetActiveWindow() aus der user32-Klasse. Die kommt in ein Allgemeines Modul (bei mir WINAPI genannt, hier für 32Bit):
Code:
Option Explicit
Declare Function GetActiveWindow Lib "user32" () As Long
Als nächstes die (rudimentär zusammengeklöppelte, undokumentierte und nicht sehr stabile(!!!)) Klasse, die dir ein Activated-Event für das ApplicationWindow spendiert. Die Klasse habe ich ApplicationWindow genannt. Weil VBA erstmal keinen Timer kennt, der in einem kürzeren Intervall als sekündlich funktioniert, läuft hier eine Dauerschleife, die alle 1000 schleifendurchläufe überprüft, ob das eingestellte Zeitintervall abgelaufen ist, um anschließend festzustellen, ob das Handle der Application mit dem gerade in Windows aktiven Windows-Handle übereinstimmt und das vorher nicht getan hat. Das ist nicht sehr stabil und nicht sehr ökonomisch sinnvoll. Letztlich kannst du deinen Rechner dabei als Heizung einsetzen. Als netten Nebeneffekt, kannst du deinen VBA-Editor während der Laufzeit nicht verwenden. Weitere Nebeneffekte sind ebenfalls nicht auszuschließen:
Code:
Option Explicit
Private HWND As Long
Private isRunning As Boolean
Private isactive As Boolean
Public Event Activated()
Private Sub Class_Initialize()
HWND = Application.HWND
End Sub
Private Sub Class_Terminate()
isRunning = False
End Sub
Sub start(intervalMiliSeconds As Long)
Dim lasttimestamp As Long
Dim stepper As Long
lasttimestamp = Timer
isRunning = True
isactive = True
Do While isRunning
stepper = stepper + 1
If stepper Mod 1000 = 0 Then
stepper = 1
If Timer > lasttimestamp + (intervalMiliSeconds / 1000) Then
If WINAPI.GetActiveWindow() = HWND Then
If Not isactive Then
RaiseEvent Activated
isactive = True
End If
Else
If isactive Then isactive = False
End If
lasttimestamp = Timer
End If
End If
DoEvents
Loop
End Sub
Sub stopMe()
isRunning = False
End Sub
Ob die Schleife über den Stepper Rechenpower spart, oder ob ein dauerhaftes Abfragen des Timers genau so funktionieren würde, müsstest du selbst ausprobieren.
Zum Testen, habe ich einfach zwei Buttons in ein Worksheet-Objekt eingefügt, und in dessen Codebehind den Event-Handler für eine eigene ApplicationWindow-Instanz implementiert. Die beiden Buttons starten und stoppen die Überwachung:
Code:
Option Explicit
Private WithEvents Wind As ApplicationWindow
Sub starten()
If Wind Is Nothing Then Set Wind = New ApplicationWindow
Wind.start 500
End Sub
Sub stoppen()
Wind.stopMe
Set Wind = Nothing
End Sub
Private Sub Wind_Activated()
Debug.Print Application.Name & " activated at " & Now()
End Sub
Private Sub CommandButton1_Click()
starten
End Sub
Private Sub CommandButton2_Click()
stoppen
End Sub
Ein Deactivated-Event ließe sich entsprechend einfach in der Hauptschleife der Klasse im Else-Zweig einbauen.
Viel Vergnügen damit und denk daran, dass das Unterfangen eher nicht nützlich ist.
Viele Grüße
derHöpp