Fenster in den Desktop-Vordergrund bringen

Veröffentlicht: 16. Aug 2001 | Aktualisiert: 13. Jun 2004

Von Mathias Schiffer

Um ein Anwendungsfenster als aktives Fenster in den Vordergrund des Desktops zu bringen, ist die API Funktion SetForegroundWindow vorgesehen. Unter Windows 98, Windows Me und Windows 2000 jedoch reagiert diese Funktion anders als unter Windows 95 und Windows NT 4.0: Die neueren Windows-Versionen bringen ein Fenster nicht mehr in den Vordergrund des Desktops. Sie lassen stattdessen die Titelzeile des betroffenen Fensters (inklusive des entsprechenden Eintrags in der Taskleiste, sofern der aufrufende Thread der Vordergrund-Thread ist) blinken, um den Benutzer auf sich aufmerksam zu machen.

In vielen Fällen ist diese Verhaltensänderung durchaus sinnvoll: Denken Sie beispielsweise an einen Anwender, der ohne ständige Betrachtung des Bildschirms eine Texteingabe vornimmt. Wird während dieses Vorgangs das aktive Fenster verändert, bemerkt der Anwender dies nicht sofort - er tippt munter weiter, was bei dem Setzen eines neuen Eingabefensters unabschätzbare Folgen haben kann (so wird etwa die Eingabetaste als vermeintlicher Zeilenumbruch in der Textverarbeitung in einem anderen Fenster schnell unbeabsichtigt zum Befehl, eine Schaltfläche zu betätigen).

Während diese Änderung in vielen Fällen sinnvoll ist, um den Anwender nicht bezüglich des aktuellen Fensters auf seinem Desktop zu "bevormunden", gibt es dennoch Situationen, in denen Sie als Entwickler trotzdem ein Fenster aktivieren und in den Vordergrund bringen möchten. Liegt dieses Fenster im gleichen Thread wie das aktuelle Vordergrundfenster, arbeitet SetForegroundWindow auch wie erwartet. Für Fenster anderer Threads jedoch tritt bei gleichem Vorgehen lediglich die blinkende Titelzeile auf.

Um dieses Problem zu umgehen, können Sie sich der API Funktion AttachThreadInput bedienen, die Ihnen Zugriff auf die Eingabeverarbeitung eines anderen Threads bietet. Haben Sie diesen Zugriff erhalten, können Sie auch unter den neueren Windows-Versionen mit SetForegroundWindow wie erwartet arbeiten:

' Verwendete API Funktionen 
Private Declare Function SetForegroundWindow _ 
  Lib "user32" ( _ 
  ByVal hwnd As Long _ 
  ) As Long 
Private Declare Function GetForegroundWindow _ 
  Lib "user32" ( _ 
  ) As Long 
Private Declare Function GetWindowThreadProcessId _ 
  Lib "user32" ( _ 
  ByVal hwnd As Long, _ 
  ByRef lpdwProcessId As Long _ 
  ) As Long 
Private Declare Function AttachThreadInput _ 
  Lib "user32" ( _ 
  ByVal idAttach As Long, _ 
  ByVal idAttachTo As Long, _ 
  ByVal fAttach As Long _ 
  ) As Long 
' Verwenden Sie die Funktion SetForegroundWindowEx statt der 
' API Funktion SetForegroundWindow ausschließlich, wenn das 
' betroffene Fenster tatsächlich in den Vordergrund gebracht 
' werden muss. 
Private Function SetForegroundWindowEx(ByVal hWndWindow As Long) As Boolean 
' Dient dem Setzen des Vordergrundfensters mit der Funktion 
' SetForegroundWindow, die sich unter neueren Windows-Versionen 
' anders verhält als unter Windows 95 und Windows NT 4.0. 
' Der Rückgabewert ist True, wenn das Fenster erfolgreich in den 
' Vordergrund gebracht werden konnte. 
Dim lThreadForeWin As Long  ' Thread-ID für das aktuelle Vordergrundfenster 
Dim lThreadWindow As Long   ' Thread-ID für das in hWndWindow spezifizierte 
                            ' Fenster, das in den Vordergrund des Desktops 
                            ' gebracht werden soll. 
  ' Falls das Fenster dem gleichen Thread wie das aktuelle 
  ' Vordergrundfenster angehört, ist kein Workaround erforderlich: 
  lThreadWindow = GetWindowThreadProcessId(hWndWindow, ByVal 0) 
  lThreadForeWin = GetWindowThreadProcessId(GetForegroundWindow(), ByVal 0) 
  If lThreadWindow = lThreadForeWin Then 
    ' Vordergrundfenster und zu aktivierendes Fenster gehören zum 
    ' gleichen Thread. SteForegroundWindow allein reicht aus: 
    SetForegroundWindowEx = CBool(SetForegroundWindow(hWndWindow)) 
  Else 
    ' Das Vordergrundfenster gehört zu einem anderen Thread als das 
    ' Fenster, das neues Vordergrundfenster werden soll. Mittels 
    ' AttachThreadInput erhaten wir kurzzeitig Zugriff auf die 
    ' Eingabeverarbeitung des Threads des Vordergrundfensters, 
    ' so dass SetForegroundWindow wie erwartet arbeitet: 
    AttachThreadInput lThreadForeWin, lThreadWindow, True 
    SetForegroundWindowEx = CBool(SetForegroundWindow(hWndWindow)) 
    AttachThreadInput lThreadForeWin, lThreadWindow, False 
  End If 
End Function 

Weiterführende Literatur:

Weitere Informationen zu diesem Thema finden Sie in der Microsoft Knowledgebase in Ihrer MSDN Library oder im MSDN Online: