BigBastis Blog

Windows Aero Glass in eigenen Projekten nutzen Teil 2

Introduction

user

Sebastian Gross

Sebastian Gross arbeitet in Bielefeld als Softwareentwickler für .NET und Java im Bereich Web.Als Fan der .NET-Plattform lässt er sich kein Userguppen Treffen und Community Event im Raum OWL entgehen.Dabei hat er eine besondere Vorliebe für das ASP.NET MVC Framework und für das Test Driven Development (TDD) entwickelt.


LATEST POSTS

Handling too long scrollspy menus 10th June, 2015

Java: Create ZIP archive 23rd March, 2015

.NET

Windows Aero Glass in eigenen Projekten nutzen Teil 2

Posted on .

dotnetIn dem ersten Teil dieses Beitrags, der nun schon einige Monate her ist habe ich gezeigt, wie man die Aero Glas Effekte auch in eigene Projekte einbauen kann. Doch leider waren da noch einige Probleme, so konnten wir nur das ganze Formular in Glas verwandeln und die Darstellung der Steuerelemente war falsch.

Genau hier möchte ich den zweiten Teil ansetzen und diese letzten Probleme aus der Welt schaffen!

Wir beginnen genauso wie im ersten Teil nur nennen wir unsere Klasse diesmal GlassForm um nicht durcheinander zu kommen.

Diesmal importieren wir eine weitere Methode aus der Windows API, nämlich DwmIsCompositionEnabled() die es uns ermöglicht zu prüfen, ob diese Effekte, die wir nutzen möchten auch verfügbar sind.

Die zweite Funktion DwmExtendFrameIntoClientArea müsste aus Teil 1 schon bekannt sein, diese hilft uns die Formränder zu vergrößern und somit die Glasoberfläche ins Formularinnere zu holen.

Da wir dieses Mal die eine Option für alle Ränder haben möchten, sodass wir zB. nur den oberen Rand in Glas verwandeln, benötigen wir ein Structure, in dem wir die Werte für jeden Rand speichern können und den wir dann später der Funktion DwmExtendFrameIntoClientArea übergeben.

So sieht unsere Klasse aus:

Imports System.Runtime.InteropServices

Public Class GlassForm
 _
        Private Shared Sub DwmExtendFrameIntoClientArea _
                (ByVal hwnd As IntPtr, ByRef margin As AeroDemo2.MARGINS)
    End Sub
 _
    Public Shared Function DwmIsCompositionEnabled() As Boolean
    End Function

    Public Shared Function ExtendGlassFrame _
        (ByVal hwnd As IntPtr, ByVal margin As AeroDemo2.MARGINS) As Boolean

        GlassForm.DwmExtendFrameIntoClientArea(hwnd, margin)

        Return True

    End Function

End Class

Public Structure MARGINS
    Public left As Integer
    Public right As Integer
    Public top As Integer
    Public bottom As Integer

    Public Sub New(ByVal l As Integer, ByVal r As Integer, _
                   ByVal t As Integer, ByVal b As Integer)
        left = l
        right = r
        top = t
        bottom = b
    End Sub
End Structure

Wie man sieht enthält die Structure MARGINS je eine Variable für jede Seite des Formulars, wobei der Wert den sie beinhaltet den Abstand zum eigentlichen Rahmen angibt!

Wechseln wir nun zur Klasse Form1, da wir hier fertig sind. In der Form_Load Methode können wir uns nun einen neuen Structure erstellen und diesem unsere gewünschten Rahmenabstände übergeben. Daraufhin rufen wir unsere Funktion auf die für sns das Glas herzaubern soll.

Doch wenn wir das Programm nun starten werden wir kein Glas vorfinden! Das liegt daran, dass Windows die Farbe Schwarz für Transparente Darstellung auf Glas verwendet. Das bedeutet, dass alle Steuerelemente, die Schwarze Farbe enthalten transparent und somit zu Glas werden! Das konntet ihr aber auch im ersten Teil schon beobachten!

Dieses Problem nehmen wir aber später nocheinmal in Angriff! Kommen wir ersteinmal zu unserem Glasfenster!

Damit wir auch wirklich Glas sehen, müssen wir ersteinmal das Fenster mit schwarzer Farbe füllen. Dazu schreiben wir folgendes in die Form_Paint Methode:

    Dim margins As AeroDemo2.MARGINS

    Private Sub Form1_Load() Handles MyBase.Load
        'Den "normalen" Bereich festlegen
        margins = New AeroDemo2.MARGINS(0, 0, 35, 50)
        'Die Fensterränder erweitern
        GlassForm.ExtendGlassFrame(Me.Handle, margins)
    End Sub

Wenn man das Programm startet, müsste das ca so aussehen:

aerodemo1Bild 1: Alles ist schwarz, bis auf den Glasteil

Bitte nicht erschrecken, denn eigentlich ist es keine Überraschung, dass wir nur schwarz sehen, denn wir haben im letzten Schritt alles Schwarz gefärbt. Der Aero Teil ist dadurch nun transparent geworden!

Da das Schwarze aber ziemlich blöd aussieht möchten wir das natürlich wieder auf unsere Standardeinstellung ändern. Dazu müssen wir diesen schwarzen Rechteck da oben nun wieder mit der Ausgangsfarbe füllen! Das machen wir so:

    Private Sub Form1_Paint(ByVal sender As Object, _
                ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        If GlassForm.DwmIsCompositionEnabled() = True Then
            'Hintergrund Schwarz füllen, um den Glass effenkt zu erhalten
            e.Graphics.Clear(Color.Black)
            'Nun das Stück, dass nicht aus Glas sein soll wieder "zurückmalen"
            Dim clientArea As New Rectangle(margins.left, margins.top, _
                    Me.ClientRectangle.Width - margins.left - margins.right, _
                    Me.ClientRectangle.Height - margins.top - margins.bottom)
            Dim b As Brush = New SolidBrush(Me.BackColor)
            e.Graphics.FillRectangle(b, clientArea)
        End If
    End Sub

Nachdem wir das Rechteck wieder mit der Ausgangsfarbe bemalt haben sieht das schon viel angenehmer aus:

aerodemo2Bild 2: Das Fenster hat nun wieder die „Normale“ Farbe

Was natürlich nun auffällt ist das Komplett schwarze Label (ja, es ist wirklich eins) und der nicht lesbare Button.

Dies sind die oben besagten Probleme von GDI Objekten. Diese werden Standardmäßig genutzt um Abwärtskompabilität zu gewährleisten. Schaltet man aber das TextRendering auf GDI+ so werden auch die Schriften korrekt dargestellt.

Um das zu ändern muss die Option SetCompatibleTextRenderingDefault auf true gesetzt werden. Dies muss aber geschehen bevor das Programm gestartet wird. Also klicken wir mit der Rechten Maustaste auf unser Projekt -> Hinzufügen -> Modul

In das Modul schreibt ihr nun folgendes rein:

    Sub Main()
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(True)
        Application.Run(New Form1) 'Name eurer Form
    End Sub

Nun müssen wir nurnoch dafür sorgen, dass unser Projekt durch das Modul gestartet wird. Das machen wir in dem wir auf „Projekt“ oben im Menü klicken und dann auf Eigenschaften. Hier muss nun der Haken bei „Anwendungsframework aktivieren“ herausnehmen und dann bei „Startobjekt“ „Sub Main“ wählen:

aerodemo2_1Bild 3: Das Projekt über das Modul starten

Wenn wir das Programm nun starten sollte man die Texte und auch den Button lesen können!

Nun sind wir eigentlich schon durch. Was noch zu sagen bleibt ist, dass man es möglichst vermeiden sollte Steuerelemente auf dem Glas zu platzieren, da diese sehr oft falsch dargestellt werden.

Wenn ihr unbedingt Schrift auf Glas haben wollt solltet ihr diese Schrift auf das Formular Zeichnen und nicht einfach über ein Label dort platzieren. Das selbe gilt auch für Grafiken. Leider kann man nicht einfach mit der Graphics.DrawString() Methode Zeichnen sondern muss den Text erst in ein GraphicsPath Objekt „zeichnen“ bevor man es dem Glas übergibt. So stellt man sicher, dass die Textverläufe richtig dargestellt werden!

Hier ein Beispiel:

            'Text zeichnen
            Dim txt = Me.CreateGraphics()
            Dim path = New GraphicsPath()

            path.AddString("Ich bin ein gezeichneter Text", _
                           New FontFamily("Tahoma"), CInt(FontStyle.Regular), _
                           20, New Point(60, 0), StringFormat.GenericDefault)

            Dim brush = New PathGradientBrush(path)
            Dim clr As Color() = {Color.Transparent}

            txt.SmoothingMode = SmoothingMode.HighQuality
            brush.CenterColor = Color.White
            brush.SurroundColors = clr
            txt.FillPath(Brushes.Black, path)

            brush.Dispose()
            path.Dispose()
            txt.Dispose()

Und wie es aussehen könnte:

aerodemo3Bild 4: So könnte ein Aero Formular aussehen

Weitere Informationen auch mit Beispielen findet ihr hier: (englisch & C#)

Microsoft
CodeProject
CodeProject

Wie üblich habe ich das Ganze in ein kleines Demoprojekt verpackt: Download

Wie hats euch gefallen, möchtet ihr einen dritten Teil? Freue mich auf euer Feedback!

Teil 1 des Tutorials gibts hier
Zum dritten Teil gehts hier lang

profile

Sebastian Gross

http://www.bigbasti.com

Sebastian Gross arbeitet in Bielefeld als Softwareentwickler für .NET und Java im Bereich Web.Als Fan der .NET-Plattform lässt er sich kein Userguppen Treffen und Community Event im Raum OWL entgehen.Dabei hat er eine besondere Vorliebe für das ASP.NET MVC Framework und für das Test Driven Development (TDD) entwickelt.

Comments
user

Author Michael

Posted at 17:30 14. November 2009.

Gute Arbeit! Danke! 🙂
Hatte aber ein paar kleine Probleme – hab mir aber dann die Demo geladen.
Nur eins noch: wie bekommt man Ne Textbox auf dem Glas dazu auch nen schwarzen Text zu haben? (kannst auch in vb-fun schreiben)

Vlt komm ich noch selber drauf wenn ich mich noch etwas mehr beschäftige.

Auf jeden fall, tolle Tutorials – hab mich schon bei mehreren eingelesen – und die Seite find ich auch funktionell.. also gut.

PS: vlt treffen wir uns ja einmal bei AA3 😉

user

Author admin

Posted at 21:01 14. November 2009.

Hallo Michael,

ja das mit den Steuerelementen auf Glas ist nicht so ganz einfach ich weis. Werde dazu demnächst wohl noch einen dritten Teil machen.
Und danke fürs Feedback!
Was ist denn das „AA3“? 🙂

user

Author Michael

Posted at 14:29 15. November 2009.

Ich möcht hier ja ned Werbung machen xD
Americas Army 3. Ist ein Relistischer Ego-Shooter entwickelt von der US Army. Wird hald fleißig gezockt. Ist Freeware.. kannst ja mal vorbeischaun
*g*

Also echt toll deine .net Tutorials 😉

user

Author Michael

Posted at 20:19 7. Dezember 2009.

Hallo BigBasti!
Also nach einigen Tests ist mir noch was aufgefallen, wirst du aber bestimmt auch schon gesehen haben.
Also wenn ich auf dem Glass einen Text anzeigen lasse (zb. wie oben „ich bin ein gezeichneter Text“), und auf dem Form arbeite (Klicks auf Elemente,…) dann wird die Schrift immer dicker – es scheint so, als ob die Schrift öfters übereinander angezeigt wird.

Also es ist ein Tolles Tutorial! Nur etwas feinarbeit an den Steuerelementen fehlt wohl.. aber das „etwas“ ist warscheinlich mit nem riesen Aufwand verbunden 🙁

Ich drück dir auf jeden Fall für weitere Projekte die Daumen,
und freu mich über jedes Tut auf deiner BlogSeite.

Gruß,
Michael

Kommentar verfassen

View Comments (4) ...
Navigation