Rubrik: Oberfläche · Effekte | VB-Versionen: VB2005, VB2008 | 16.02.09 |
Clientarea einer Form abdunkeln bzw. transparent färben Mit diesen Funktionen erzielen einen schönen Ein-/Ausblendeffekt für Formen, wenn diese bspw. aktiviert oder deaktiviert werden, indem der Clientbereich der Form langsam abgedunkelt wird. | ||
Autor: Dietrich Herrmann | Bewertung: | Views: 14.292 |
ohne Homepage | System: Win2k, WinXP, Win7, Win8, Win10, Win11 | Beispielprojekt auf CD |
Sie kennen den Effekt sicherlich von Windows Vista. Bei bestimmten Aktionen schaltet sich der Sicherheitsdialog der Benutzerkontensteuerung ein, wobei der komplette Desktop-Bereich abgedunkelt wird.
Diesen Effekt, also das Abdunkeln einer Form, erzielen Sie ab sofort mit nachfolgendem Code. Im unserem Beispiel wird der Clientbereich der Form autom. abgedunkelt, wenn das Fenster den Fokus verliert, weil bspw. eine andere Form angezeigt oder zu einer anderen Anwendung gewechselt wird.
Und so funktioniert's
Zur Laufzeit wird der Form ein zunächst unsichtbares PictureBox-Control hinzugefügt. Wird die Form deaktiviert, wird vom Clientbereich der Form ein "Screenshot" erstellt und der PictureBox
zugewiesen. Die PictureBox wird dann vollständig über den Clientbereich gesetzt. Via Timer wird das Bild dann langsam abgedunkelt.
Ein wirklich schöner Effekt
Imports System.Drawing.Imaging Public Class Form1 ' Für Ein-/Ausblend-Effekte Private WithEvents timerFadeIn As Timer Private WithEvents timerFadeOut As Timer ' Ein-/Ausblend-Einstellungen Public Enum blendOpacity ' Beginn-Transparenz der Überdeckungsfarbe blendBegin = 0 ' Schrittweite für Ein/Ausblenden blendStep = 4 ' Ende-Transparenz der Überdeckungsfarbe blendEnd = 156 ' Timer-Intervall für das Einblenden (Geschwindigkeitsregulierung) blendIntervalIn = 20 ' Timer-Intervall für das Ausblenden blendIntervalOut = 10 End Enum ' aktuelle Transparenzstufe Dim blendActual As Short = blendOpacity.blendBegin ' Farbe für die Überdeckung Dim blendColor As Color = Color.Black Dim iTimer As Short ' PictureBox für die Aufnahme des Screenshots Dim pbBlend As PictureBox
Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load ' PictureBox-Objekt erstellen pbBlend = New PictureBox Me.Controls.Add(pbBlend) pbBlend.SizeMode = PictureBoxSizeMode.AutoSize AddHandler pbBlend.Paint, AddressOf Me.pbPaint ' Wichtig! pbBlend.BringToFront() ' Timer für Ein-/Ausblendeffekt timerFadeIn = New Timer timerFadeIn.Interval = blendOpacity.blendIntervalIn timerFadeOut = New Timer timerFadeOut.Interval = blendOpacity.blendIntervalOut End Sub
Private Sub Form1_Activated(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Activated If pbBlend.Visible Then ' Einblend-Effekt starten timerFadeOut.Enabled = True End If End Sub
Private Sub Form1_Deactivate(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Me.Deactivate ' Clientbereich festlegen If captClient(Me, pbBlend, _ IIf(CheckBox1.Checked, 0, Panel2.Height), _ IIf(CheckBox2.Checked, 0, Panel1.Height), 0, 0) Then ' Ausblend-Effekt starten (abdunkeln) pbBlend.Visible = True timerFadeIn.Enabled = True End If End Sub
Private Sub pbPaint(ByVal sender As Object, _ ByVal e As System.Windows.Forms.PaintEventArgs) ' Größe des Rechtecks Dim re As Rectangle With pbBlend re = New Rectangle(.ClientRectangle.Left, _ .ClientRectangle.Top, _ .ClientSize.Width, _ .ClientSize.Height) End With ' Farbe Dim theBrush As SolidBrush = New SolidBrush( _ Color.FromArgb(blendActual, blendColor)) ' Rechteck füllen e.Graphics.FillRectangle(theBrush, re) End Sub
Private Sub timerFadeIn_Tick(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles timerFadeIn.Tick ' Fade in Effekt iTimer += blendOpacity.blendStep If iTimer >= blendOpacity.blendEnd Then blendActual = blendOpacity.blendEnd timerFadeIn.Enabled = False End If If timerFadeIn.Enabled Then blendActual = iTimer pbBlend.Refresh() Else pbBlend.Visible = True End If End Sub
Private Sub timerFadeOut_Tick(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles timerFadeOut.Tick ' Fade out Effekt iTimer -= blendOpacity.blendStep If iTimer <= blendOpacity.blendBegin Then blendActual = blendOpacity.blendBegin timerFadeOut.Enabled = False End If If timerFadeOut.Enabled Then blendActual = iTimer pbBlend.Refresh() Else pbBlend.Visible = False End If End Sub
''' <summary> ''' Erstellt einen Screenshot der Client-Area einer Form ''' </summary> ''' <param name="fo">Form</param> ''' <param name="pb">PictureBox für den Screenshot</param> ''' <param name="cutTop">Schnitt von oben, wenn von Clientarea noch was ''' weggeschnitten werden soll</param> ''' <param name="cutBottom">Schnitt von unten</param> ''' <param name="cutLeft">Schnitt von links</param> ''' <param name="cutRight">Schnitt von rechts</param> ''' <param name="doGray">Screenshot als Graustufenbild oder nicht</param> Public Function captClient(ByVal fo As Form, ByVal pb As PictureBox, _ ByVal cutTop As Short, ByVal cutBottom As Short, _ ByVal cutLeft As Short, ByVal cutRight As Short, _ Optional ByVal doGray As Boolean = False) As Boolean Dim w As Integer = fo.Width Dim cw As Integer = fo.ClientSize.Width Dim h As Integer = fo.Height Dim ch As Integer = fo.ClientSize.Height Dim dw As Integer = w - cw Dim dh As Integer = h - ch ' Wenn Höhe oder Breite < 1... If w < 1 OrElse h < 1 OrElse cw < 1 OrElse ch < 1 Then Return False Dim bm As New Bitmap(w, h) ' ganze Form in die Bitmap zeichnen fo.DrawToBitmap(bm, New Rectangle(0, 0, w, h)) Dim bmc As New Bitmap(CInt(dw / 2), ch - cutTop) ' den Screenshot der Form beschneiden bmc = CropBitmap(bm, dw / 2, dh - dw / 2 + cutTop, _ cw, ch - cutTop - cutBottom) With pb .Left = cutLeft .Top = cutTop If doGray Then ' eventuell Graustufenbild vom Screenshot machen .Image = GetGrayScaleImage(bmc) Else .Image = bmc End If End With Return True End Function
''' <summary> ''' Beschneidet ein Bitmap ''' </summary> ''' <param name="bmp"></param> ''' <param name="cropX">X-Koordinate</param> ''' <param name="cropY">Y-Koordinate</param> ''' <param name="cropWidth">Breite</param> ''' <param name="cropHeight">Höhe</param> Public Function CropBitmap(ByRef bmp As Bitmap, _ ByVal cropX As Integer, ByVal cropY As Integer, _ ByVal cropWidth As Integer, ByVal cropHeight As Integer) As Bitmap Dim rect As New Rectangle(cropX, cropY, cropWidth, cropHeight) Dim cropped As Bitmap = bmp.Clone(rect, bmp.PixelFormat) Return cropped End Function
' This method draws a grayscale image from a given Image-instance ' and gives back the Bitmap of it img- the original bitmap Public Function GetGrayScaleImage(ByVal img As Image) As Bitmap Dim grayBitmap As New Bitmap(img.Width, img.Height) Dim imgAttributes As New ImageAttributes() Dim gray As New ColorMatrix(New Single()() { _ New Single() {0.299F, 0.299F, 0.299F, 0, 0}, _ New Single() {0.588F, 0.588F, 0.588F, 0, 0}, _ New Single() {0.111F, 0.111F, 0.111F, 0, 0}, _ New Single() {0, 0, 0, 1, 0}, _ New Single() {0, 0, 0, 0, 1}}) imgAttributes.SetColorMatrix(gray) Dim g As Graphics = Graphics.FromImage(grayBitmap) g.DrawImage(img, New Rectangle(0, 0, img.Width, img.Height), _ 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imgAttributes) Return grayBitmap End Function
End Class
Kurze Erläuterung zu den Funktionen:
Die Funktion captClient macht einen Screenshot von der Clientarea einer Form. Als Parameter werden erwartet:
- Form-Objekt
- Picturebox-Objekt, das den Screenshot aufnehmen muss
- 4 Korrekturkoordinaten (damit kann man den Screenshot an allen vier Seiten beschneiden; bspw. die Höhe eines Toolstrips am oberen Rand und die Höhe eines StatusStrips am unteren Rand der Form)
- Boolean-Wert, ob der Screenshot noch in ein Graustufenbild konvertiert werden soll oder nicht
Die Paint-Prozedur der PictureBox wird in Timer-Prozeduren aufgerufen. Es gibt einen TimerFadein und einen TimerFadeout.
Am Besten das Beispielprojekt einmal ausführen, da sieht man, wie das Prinzip funktioniert.
In diesem Falle wird also die Clientarea farbig 'gecaptured' und dann mit halbtransparentem Schwarz 'übermalt'. Mit den oben genannten Einstellungen kann alles beliebig gesteuert werden.
That's it, have fun.