vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Zippen wie die Profis!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: Forms/Controls   |   VB-Versionen: VB601.10.08
Informationen außerhalb des eigenen Programms darstellen

Mit diesem Workshop wird eine Möglichkeit aufgezeigt, InfoBoxen bzw. Informationen außerhalb der eigenen Anwendung darzustellen, und zwar so, dass nur der reine Text bzw. die Controls sichtbar sind, d.h. die Form selbst wird transparent dargestellt.

Autor:  RobertBewertung:     [ Jetzt bewerten ]Views:  12.960 

Denjenigen, die schon einmal vergeblich versucht haben, Informationen außerhalb der eigenen Form so darzustellen, dass man wirklich nur die Zeichen selbst und kein Formular etc. sieht, sei hier und heute geholfen.

Das Problem:
Man möchte zum Beispiel über der Oberfläche eines Fremdprogramms eine Information wie etwa die aktuelle Systemzeit darstellen, weiß aber nicht wie, denn auf die Programmoberfläche des Fremdprogramms kann - wenn überhaupt - nur schwer zugegriffen werden und passende API-Funktionen sind mir auch nicht bekannt.

Die Lösung:
Es ist eigentlich recht simpel. Man nimmt sich ein kleines Formular, setzt ein Label drauf und stellt es transparent über dem Fremdprogramm dar. Um das aber universeller zu gestalten, werden wir diese Funktion heute in einem Modul verankern.

Soweit das Grobe, jetzt noch einmal langsam ;)

Starten Sie ein neues Projekt und fügen Sie noch eine Form hinzu. Nennen wir sie „frmBase". Platzieren Sie weiterhin ein Label auf dieser Form. Um den bestmöglichen Transparenzeffekt zu erzielen, sollte man noch folgende Einstellungen vornehmen:

frmBase.BorderStyle = 0
Label1.BackStyle = 1

Durch die erste Zeile nehmen wir dem Formular seine Titelleiste weg (und somit uns die Möglichkeit, es wie gewohnt zu verschieben - das muss aus unserer Hauptform heraus geschehen). Die zweite Zeile dient lediglich dem Effekt der Transparenz.

Nun machen wir uns an das Modul. Fügen Sie eins Ihrem Projekt hinzu und nennen Sie es „modInfoBox".

Im Deklarationsteil brauchen wir folgenden Code:

Option Explicit
 
Dim frm2() As Form
Private Counter As Integer
Dim i As Integer
 
Private Declare Function SetWindowPos Lib "user32" ( _
  ByVal hwnd As Long, _
  ByVal hWndInsertAfter As Long, _
  ByVal x As Long, _
  ByVal y As Long, _
  ByVal cx As Long, _
  ByVal cy As Long, _
  ByVal wFlags As Long) As Long
 
Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2
Private Const SWP_NOMOVE = &H2
Private Const SWP_NOSIZE = &H1

Erläuterung: frm2() ist ein Array, das Formen beinhaltet. Hier werden wir nachher dynamisch unsere InfoBoxen hineinladen. Die Variable Counter wird die Anzahl unserer InfoBoxen zählen und die Variable i ist die Zählvariable einer For-Schleife. Die API-Funktion SetWindowPos und die 4 dazugehörigen Konstanten brauchen wir erst später, nämlich um unsere InfoBoxen, wenn wir das wollen, permanent in den Vordergrund zu setzen.

Bevor wir jetzt mit modInfoBox fortfahren können, brauchen wir ein weiteres Modul namens modTransparentForm mit folgendem Code:

Option Explicit
 
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 Declare Function SetLayeredWindowAttributes Lib "user32" ( _
  ByVal hwnd As Long, _
  ByVal crey As Long, _
  ByVal bAlpha As Byte, _
  ByVal dwFlags As Long) As Long
 
Private Const gwl_ExStyle = (-20)
Private Const ws_Ex_Layered = &H80000
Private Const LWA_ALPHA = &H2&
Private Const lwa_ColorKey = 1
Public Sub setTransparencyFormOnly(Form As Form, _
  ColorToFade As ColorConstants)
 
  Call SetWindowLong(Form.hwnd, gwl_ExStyle, _
    GetWindowLong(Form.hwnd, gwl_ExStyle) Or ws_Ex_Layered)
  Call SetLayeredWindowAttributes(Form.hwnd, ColorToFade, 0, lwa_ColorKey)
End Sub
Public Sub setTransparencyAlsoControls(Form As Form, _
  TransparencyLevel As Byte)
 
  Call SetWindowLong(Form.hwnd, gwl_ExStyle, _
    GetWindowLong(Form.hwnd, gwl_ExStyle) Or ws_Ex_Layered)
  Call SetLayeredWindowAttributes(Form.hwnd, 0, TransparencyLevel, LWA_ALPHA)
End Sub
Public Sub setToNormal(Form As Form)
  Call SetWindowLong(Form.hwnd, gwl_ExStyle, _
    GetWindowLong(Form.hwnd, gwl_ExStyle) And (Not ws_Ex_Layered))
  Call SetLayeredWindowAttributes(Form.hwnd, 0, 255, LWA_ALPHA)
End Sub

In diesem Modul erledigen wir alles, was mit Transparenz zu tun hat. Im Groben wird hier mit den drei API's die WindowLong-Eigenschaft verändert. Und zwar gibt es da verschiedene Möglichkeiten:

  • setTransparencyFormOnly: Diese Funktion macht ein Formular transparent - aber nur das Formular, nicht die Steuerelemente, die es besitzt! Dies geschieht anhand einer vorher festgelegten Farbe, die der Funktion via ColorToFade übergeben wird. Will ich also meine Form transparent haben, setze ich zuerst die BackColor z.B. auf vbRed und rufe dann die Funktion auf, indem ich als ersten Parameter mein Formular und als zweiten einfach vbRed übergebe.
     
  • setTransparencyAlsoControls: Hier werden auch die Controls transparent gemacht. Und zwar geschieht das nicht wie eben anhand einer Farbe, sondern es wird dem Formular als Ganzes ein Alpha-Wert zugewiesen, der der Funktion über das Argument TransparencyLevel übergeben wird. Dabei bedeutet 0 völlige Transparenz und 255 die „normale" Transparenz, nämlich keine.
     
  • setToNormal: Wie der Name schon sagt, wird die Transparenz eines Fensters hier wieder aufgehoben.

Damit ist unser Transparenz-Modul fertig. Es kann übrigens bei jedem VB-Projekt benutzt werden.

Kommen wir nun zurück zu unserem „Hauptmodul" modInfoBox.

Zuerst einige Hilfsfunktionen. Ich werde nun größtenteils auf die Erläuterungen verzichten, da der Code ausreichend kommentiert ist.

' Schließt eine einzelne InfoBox
' Param: Index = Indexnummer der jeweiligen InfoBox
Public Sub TerminateInfoBox(index As Integer)
  Unload frm2(index)
End Sub
' Schließt alle InfoBoxen
' Rückgabe: Anzahl der geschlossenen InfoBoxen
Public Function TerminateAllInfoBoxes() As Long
  Dim tmpCount As Long
  Dim i As Long
 
  ' Unload für jedes Element im Array
  For i = 0 To UBound(frm2())
    Unload frm2(i)
    tmpCount = tmpCount + 1
  Next i
  ReDim Preserve frm2(0)
 
  Counter = 0
  TerminateAllInfoBoxes = tmpCount
End Function
' Macht alle InfoBoxen wieder undurchsichtig
Public Sub setAllInfoBoxesIntransparent()
  Dim i As Long
 
  For i = 0 To UBound(frm2())
    modTransparentForm.setToNormal frm2(i)
  Next i
End Sub
' Macht alle InfoBoxen transparent
Public Sub setAllInfoBoxesTransparent()
  Dim i As Long
 
  For i = 0 To UBound(frm2())
    modTransparentForm.setTransparencyFormOnly frm2(i), frm2(i).BackColor
  Next i
End Sub
' Bindet eine einzelne InfoBox an den Vordergrund
' Param: Index = Indexnummer der jeweiligen InfoBox
Public Sub setSingleInfoBoxToTop(ByVal index As Long)
  setFormOnTop frm2(index).hwnd, True
End Sub
' Bindet alle InfoBoxen an den Vordergrund
Public Sub setAllInfoBoxesToTop()
  Dim i As Long
 
  For i = 0 To UBound(frm2())
    setFormOnTop frm2(i).hwnd, True
  Next i 
End Sub
' Löst eine einzelne InfoBox vom Vordergrund, so dass wieder normal
' Param: Index = Indexnummer der jeweiligen InfoBox
Public Sub releaseSingleInfoBoxFromTop(ByVal index As Long)
  setFormOnTop frm2(index).hwnd, False
End Sub
' Löst alle InfoBoxen vom Vordergrund, so dass wieder normal
Public Sub releaseAllInfoBoxesFromTop()
  Dim i As Long
 
  For i = 0 To UBound(frm2())
    setFormOnTop frm2(i).hwnd, False
  Next i
End Sub
' Greift auf eine InfoBox zu und verändert sie
' Param: Index = Indexnummer der jeweiligen InfoBox
Public Sub EditInfoBox(ByVal index As Integer, ByVal Display1 As String)
  frm2(index).Label1.Caption = Display1
End Sub
' Greift auf alle InfoBoxen zu und verändert sie
' Param: Display1 = String, der dargestellt werden soll
' Rückgabe: Anzahl der veränderten InfoBoxen
'
' Anmerkung: Diese Funktion muss auf die individuelle InfoBox-Form 
' zugeschnitten sein
Public Function EditAllInfoBoxes(ByVal Display1 As String) As Long
  Dim i As Long
 
  EditAllInfoBoxes = 0
  For i = 0 To UBound(frm2())
    frm2(i).Label1.Caption = Display1
    EditAllInfoBoxes = EditAllInfoBoxes + 1
  Next i
End Function
' Bindet ein Fenster an den Vordergrund
' Param: hwnd = Fensternummer des entspr. Fensters
'       OnTop = Fenster immer im Vordergrund -> ja/nein
Public Sub setFormOnTop(ByVal hwnd As Long, ByVal OnTop As Boolean)
  If OnTop Then
    ' immer im Vordergrund
    SetWindowPos hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE
  Else
    ' normal
    SetWindowPos hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE
  End If
End Sub

Soweit die ganzen kleinen Nebenfunktionen. Jetzt schreiten wir voran zum Herz unseres Moduls, nämlich zu der Funktion, die die InfoBox erstellt:

' Erstellt eine transparente InfoBox auf Basis eines Formulars
' Param: FormSource = Modell der InfoBox
'        ColorToFade (optional) = Farbe, die transparent gemacht werden
'                                 soll. Wenn weggelassen, wird keine 
'                                 Transparenz gezeigt
'        TwipsX = X-Position der InfoBox in Twips
'        TwipsY = Y-Position der InfoBox in Twips
'        FormOnTop = InfoBox immer im Vordergrund?
'
' Rückgabe: Index der gerade erzeugten InfoBox im Form-Array
Public Function CreateNewInfoBox(FormSource As Form, _
  ByVal TwipsX As Long, ByVal TwipsY As Long, _
  Optional ByVal FormOnTop As Boolean = False, _
  Optional ByVal ColorToFade As ColorConstants = -1) As Long
 
  ' dem Array, das die InfoBoxen beinhaltet, eine weitere InfoBox hinzufügen
  ReDim Preserve frm2(0 To Counter)
  Set frm2(Counter) = FormSource
 
  ' InfoBox bauen
  Load frm2(Counter)
  With frm2(Counter)
    .Label1.BackStyle = 0
 
    ' wenn der optionale Parameter ColorToFade angegeben wurde:
    If ColorToFade <> -1 Then .BackColor = ColorToFade
 
    .BorderStyle = 0
    .Left = TwipsX
    .Top = TwipsY
    .Show
  End With
 
  ' wenn gewünscht, InfoBox in den Vordergrund
  If FormOnTop = True Then setFormOnTop frm2(Counter).hwnd, True
 
  ' Transparenz setzen, wenn ColorToFade angegeben
  If ColorToFade <> -1 Then
    modTransparentForm.setTransparencyFormOnly frm2(Counter), ColorToFade
  End If
 
  ' aktuellen Index zurückgeben, damit die einzelnen InfoBoxen später
  ' besser angesprochen werden können
  CreateNewInfoBox = Counter
 
  Counter = Counter + 1
End Function

Ich bitte zu beachten, dass die Koordinatenangaben in Twips gemacht werden müssen! Wer die Angaben nur in Pixel hat, kann auf folgenden Tipp zurückgreifen:
 Umrechnung Twips in Pixel und umgekehrt

Nun sind wir eigentlich fertig mit den Modulen. Jetzt kann getestet werden

Dazu nehmen wir uns wieder unser Startformular Form1, platzieren ein paar Buttons und probieren nach Herzenslust aus. Hier ein paar Beispiele für die Funktionsaufrufe:

' 3 InfoBoxen erstellen und gleich mit Text ausstatten
Dim index As Long
 
index = modInfoBox.CreateNewInfoBox(New frmStatus, 2000, 2000, True, vbGreen)
modInfoBox.EditInfoBox index, "Index Nr. " & index
 
index = modInfoBox.CreateNewInfoBox(New frmStatus, 3000, 3000, True, vbGreen)
modInfoBox.EditInfoBox index, "Index Nr. " & index
 
index = modInfoBox.CreateNewInfoBox(New frmStatus, 4000, 4000, True, vbGreen)
modInfoBox.EditInfoBox index, "Index Nr. " & index
 
MsgBox "Childs: " & index + 1
' Alle InfoBoxen transparent
modInfoBox.setAllInfoBoxesTransparent
' Alle InfoBoxen wieder normal
modInfoBox.setAllInfoBoxesIntransparent
' Alle InfoBoxen editieren
' Rückgabe ist die Anzahl der veränderten InfoBoxen
MsgBox modInfoBox.EditAllInfoBoxes("Und sie dreht sich doch!")
' Alle InfoBoxen schließen
' Rückgabe ist die Anzahl der geschlossenen InfoBoxen
MsgBox modInfoBox.TerminateAllInfoBoxes & " Fenster geschlossen"
' Alle InfoBoxen in den Vordergrund holen
modInfoBox.setAllInfoBoxesToTop
' Alle InfoBoxen nicht mehr permanent an den Vordergrund bilden
modInfoBox.releaseAllInfoBoxesFromTop

Das waren nur ein paar mögliche Aufrufe. Viele Funktionen, die sich auf alle geöffneten InfoBoxen beziehen, existieren auch noch als Variante, die sich auf nur eine InfoBox bezieht. Hierbei muss der Index der InfoBox bekannt sein, der bei der Create-Funktion zurückgegeben wird.

Ich hoffe ich habe meinen ersten Workshop relativ verständlich geschrieben und einigen, die das selbe Problem hatten wie ich, weiterhelfen können.

Viel Spaß damit

Dieser Workshop wurde bereits 12.960 mal aufgerufen.

Über diesen Workshop im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Workshop, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Workshops finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6
(einschl. Beispielprojekt!)

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
   

Druckansicht Druckansicht Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel