Aus den Newsgroups - Durchsichtige Fenster (ab Windows 2000)

Veröffentlicht: 19. Mai 2003 | Aktualisiert: 11. Nov 2004

Von Mathias Schiffer

Die Microsoft Newsgroups sind eine Quelle schier unerschöpflichen Wissens, das nahezu auf Knopfdruck abrufbar ist: Hunderte deutschsprachige Entwickler vom Einsteiger bis zum Profi treffen sich hier täglich virtuell, um Fragen zu stellen oder zu beantworten. Auch themennahe Probleme, Ansichten und Konzepte werden miteinander diskutiert. Sie kennen die Microsoft Newsgroups noch nicht? Detaillierte Information für Ihre Teilnahme finden Sie auf der Homepage der Microsoft Support Newsgroups.

Diese Kolumne greift regelmäßig ein besonders interessantes oder häufig nachgefragtes Thema aus einer der Entwickler-Newsgroups auf und arbeitet es aus.

Auf dieser Seite

 Aus der Visual Basic Newsgroup microsoft.public.de.vb:

Aus der Visual Basic Newsgroup microsoft.public.de.vb:

Ich habe einige Programme gesehen, die unter Windows XP die Fenster zu einem gewissem Prozentgrad transparent machen können. (Wie) geht das auch mit VB?

Diese Möglichkeit wird nicht nur unter Windows XP, sondern auch schon unter Windows 2000 vom Betriebssystem angeboten. Außen vor bleiben bei dieser Möglichkeit allerdings Windows 95/98 und Windows Me.

Der Schlüssel zur Transparenz eines Fensters ist die API-Funktion SetLayeredWindowAttributes gemeinsam mit einem neuen, erweiterten Fensterstil, der durch die Konstante WS_EX_LAYERED beschrieben wird. Diesen neuen Fensterstil müssen Sie einem Fenster zunächst zuweisen, um es transparent erscheinen lassen zu können.

Erweiterten Fensterstil WS_EX_LAYERED setzen
Für das Setzen dieses Fensterstils verwenden Sie die API-Funktion SetWindowLong gemeinsam mit der für erweiterte Fensterstile zuständigen Konstanten GWL_EXSTYLE. Um den bereits bestehenden Fensterstil durch diese Aktion nicht zu verfälschen, ermitteln Sie zuvor mithilfe der Funktion GetWindowLong den bestehenden Wert für den erweiterten Fensterstil. Diesen erweitern Sie danach durch eine bitweise Or-Verknüpfung um den Wert von WS_EX_LAYERED:

' Notwendige API-Deklarationen: 
Private Const GWL_EXSTYLE   As Long = -20& 
Private Const WS_EX_LAYERED As Long = &H80000 
Private Declare Function GetWindowLong _ 
  Lib "user32" Alias "GetWindowLongA" ( _ 
  ByVal hWnd As Long, _ 
  ByVal nIndex As Long _ 
  ) As Long 
Private Declare Function SetWindowLong _ 
  Lib "user32" Alias "SetWindowLongA" ( _ 
  ByVal hWnd As Long, _ 
  ByVal nIndex As Long, _ 
  ByVal dwNewLong As Long _ 
  ) As Long 
' ... 
Dim lExStyle As Long ' Stilbits erweiterter Fensterstil 
Dim hWnd As Long  ' Fensterhandle 
  hWnd = Form1.hWnd  ' Fensterstil von Form1 verändern 
  ' Bestehenden Wert für den erw. Fensterstil ermitteln: 
  lExStyle = GetWindowLong(hWnd, GWL_EXSTYLE) 
  ' Diesen Wert um WS_EX_LAYERED ergänzen: 
  lExStyle = lExStyle Or WS_EX_LAYERED 
  ' Den veränderten Fensterstil setzen: 
  SetWindowLong hWnd, GWL_EXSTYLE, lExStyle

Möchten Sie den erweiterten Fensterstil WS_EX_LAYERED später wieder entfernen, gehen Sie absolut analog vor. Statt der Or-Verknüpfung verwenden Sie jedoch eine And Verknüpfung mit dem durch den Not-Operator negierten Wert der Konstanten:

  ' Bestehenden Wert für den erw. Fensterstil ermitteln: 
  lExStyle = GetWindowLong(hWnd, GWL_EXSTYLE) 
  ' WS_EX_LAYERED löschen (egal, ob gesetzt oder nicht): 
  lExStyle = lExStyle And Not WS_EX_LAYERED 
  ' Den veränderten Fensterstil setzen: 
  SetWindowLong hWnd, GWL_EXSTYLE, lExStyle

Transparenzinformationen zuweisen
Haben Sie den erweiterten Fensterstil eines Fensters auf diese Weise um den Wert WS_EX_LAYERED erweitert, können Sie die Funktion SetLayeredWindowAttributes aufrufen.

Da diese Funktion erst ab Windows 2000 zur Verfügung steht, sollten Sie Ihren Code entweder zunächst überprüfen lassen, ob die Funktion auf dem Zielsystem zur Verfügung steht (vgl. MSDN Quickie "Verfügbarkeit ausgewählter API-Funktionen prüfen"). In unserem folgenden Beispiel wollen wir der Einfachheit halber die "Trial & Error"-Variante verwenden, den bei Nichtverfügbarkeit der aufgerufenen Funktion auftretenden Laufzeitfehler mittels On Error Resume Next schlicht zu ignorieren.

Der Transparenzgrad eines Fensters lässt sich der Funktion als Wert zwischen 0 (komplett durchsichtig) und 255 (gänzlich undurchsichtig) angeben. Mit diesem Wert wird ihr Parameter bAlpha versorgt, während dem Parameter dwFlags hierfür der Wert der Konstanten LWA_ALPHA zugewiesen wird:

' Notwendige API-Deklarationen: 
Private Const LWA_ALPHA As Long = &H2& 
Private Declare Function SetLayeredWindowAttributes _ 
  Lib "user32" ( _ 
  ByVal hWnd As Long, _ 
  ByVal crKey As Long, _ 
  ByVal bAlpha As Byte, _ 
  ByVal dwFlags As Long _ 
  ) As Long 
' ... 
On Error Resume Next ' Falls nicht Windows 2000/XP 
' Beispiel: Form1 halb transparent anzeigen 
SetLayeredWindowAttributes Form1.hWnd, 0, 127, LWA_ALPHA

Auch der ursprünglichen Fragestellung lässt sich schon entnehmen, dass ein Transparenzwert zwischen 0 und 255 ein wenig unhandlich ist. Noch dazu würde man beim "Vollausschlag" mit dem Wert 255 für eine Transparenzfunktion eher ein komplett transparentes als ein gänzlich undurchsichtiges Fenster erwarten. Handlicher wäre also eine Variante, mit der sich ein Transparenzgrad von 0% bis 100% angeben ließe. Für diesen kleinen Komfort ist natürlich nicht mehr als eine simple Rechnung notwendig:

Dim Transparenzwert As Long 
  Transparenzwert = (1 - Prozentwert / 100) * 255

Zusammenfassendes Beispiel
Hiermit sind alle Zutaten für eine komfortable Lösung angesammelt, um Fenster unter Windows 2000 und Windows XP dosiert durchsichtig anzeigen zu können. Das abschließende Beispiel stellt noch einmal alle Schritte zusammen. Viel Erfolg!

Tipp: Kopieren Sie den gesamten Quelltext zunächst in WRITE.EXE und erst von dort aus in Ihre Entwicklungsumgebung, um den Verlust von Zeilenumbrüchen zu vermeiden.

Private Const GWL_EXSTYLE   As Long = -20& 
Private Const WS_EX_LAYERED As Long = &H80000 
Private Declare Function GetWindowLong _ 
  Lib "user32" Alias "GetWindowLongA" ( _ 
  ByVal hWnd As Long, _ 
  ByVal nIndex As Long _ 
  ) As Long 
Private Declare Function SetWindowLong _ 
  Lib "user32" Alias "SetWindowLongA" ( _ 
  ByVal hWnd As Long, _ 
  ByVal nIndex As Long, _ 
  ByVal dwNewLong As Long _ 
  ) As Long 
Private Const LWA_ALPHA As Long = &H2& 
Private Declare Function SetLayeredWindowAttributes _ 
  Lib "user32" ( _ 
  ByVal hWnd As Long, _ 
  ByVal crKey As Long, _ 
  ByVal bAlpha As Byte, _ 
  ByVal dwFlags As Long _ 
  ) As Long 
Public Sub SetWindowTransparency(ByVal hWnd As Long, _ 
   Optional ByVal Percentage As Long = 50, _ 
   Optional ByVal Active As Boolean = True) 
' Setzt die Transparenz des durch hWnd angegebenen Fensters 
' auf den prozentualen Wert Percentage, sofern möglich 
' (Voraussetzung: Windows 2000/XP oder neuer). Über den Parameter 
' Active kann die Funktionalität ein- und ausgeschaltet werden. 
Dim lExStyle As Long   ' Stilbits erweiterter Fensterstil 
Dim TransparentValue As Long ' Transparenzwert 
 ' Bestehenden Wert für den erw. Fensterstil ermitteln: 
  lExStyle = GetWindowLong(hWnd, GWL_EXSTYLE) 
  If Active Then 
 ' Diesen Wert um WS_EX_LAYERED ergänzen: 
 lExStyle = lExStyle Or WS_EX_LAYERED 
  Else 
 ' WS_EX_LAYERED löschen (egal, ob gesetzt oder nicht): 
 lExStyle = lExStyle And Not WS_EX_LAYERED 
  End If 
  ' Den veränderten Fensterstil setzen: 
  SetWindowLong hWnd, GWL_EXSTYLE, lExStyle 
  ' Prozentwert in Transparenzwert (0...255) umrechnen: 
  TransparentValue = (1 - Percentage / 100) * 255 
  On Error Resume Next ' Falls nicht Windows 2000/XP 
  ' Transparenzwert setzen: 
  SetLayeredWindowAttributes hWnd, 0, TransparentValue, LWA_ALPHA 
End Sub