Videohintergründe in WPF und eine VideoUhr für Ihren Desktop

by Ramona Leenings 12. Oktober 2009 13:02

Eine VideoUhr für ihren Desktop, ganz einfach mit WPF.

Mit der Technik, die diesem schicken und äußerst beeindruckend anmutenden Programmierwerk zugrunde liegt, wird Sie dieser Blog vertraut machen. Sie müssen kein Experte sein, um dieses oder ähnliche Projekte nachbauen bzw. entwerfen zu können.

Das gesamte Projekt finden Sie im Anhang zum Download bereit gestellt. Sie können die VideoUhr anschauen, indem Sie die Anwendung nach dem Laden in VisualStudio starten. clip_image002

So (oder ähnlich ;-)) sehen Sie die Uhr und das laufende Video auf ihrem Desktop. Sollten Sie jetzt sagen, dass Sie aber gar kein Video in Ihrer Desktop Uhr laufen haben wollen, dann kann ich Ihnen versichern, dass Sie auch wahlweise ein Bild oder einen Farbverlauf mit ihren Lieblingsfarben einbauen können.

Mit WPF ist alles möglich.

Und das mit vergleichsweise wenig Aufwand. Denn jedem Steuerelement in WPF, das in irgendeiner Weise Inhalt anzeigen kann (also eine Content-Eigenschaft hat), können Sie beliebige Inhalte zuweisen. Seien es Videos, Bilder, Farben oder sonstiges. Und diese Tatsache lässt erahnen dass WPF einfach unglaublich flexibel ist und ganz neue Möglichkeiten bietet.

Schauen wir uns den Code für den Videohintergrund an.

Dim Videobackground As New VideoDrawing
Dim myVideoPlayer As New MediaPlayer
myVideoPlayer.Open(New Uri(http://shralp.com/sendung/shralp132.wmv,_  UriKind.RelativeOrAbsolute))
Videobackground.Rect = New Rect(0, 0, 300, 300)
Videobackground.Player = myVideoPlayer
Dim drawingBrush As New DrawingBrush
drawingBrush.Drawing = Videobackground
drawingBrush.Opacity = 0.7
myVideoPlayer.Play

Wir instanzieren eine neue VideoDrawing Klasse, sowie einen neuen MediaPlayer. Dem MediaPlayer wird die Uri des Videos  [myVideoPlayer.Open(New Uri(“..”))], sowie ein “Bildschirm-Bereich” zugewiesen, damit er weiß welches Video er abspielen soll, wie groß die Anzeige ist und wo sie sich positioniert. Die Position beschreiben die ersten beiden übergebenen Zahlen (0,0) und die Größe die an die Position angerechneten Größenmasse (300,300) für die Höhe und die Breite. Der MediaPlayer wird dem VideoDrawing als Player zugewiesen. Der MediaPlayer übernimmt also für das VideoDrawing das Abspielen des Videos, wohingegen das VideoDrawing das Video “hostet”.

Das VideoDrawing an sich muss auch "gehostet” werden. Ohne die daraufhin instanzierte DrawingBrush, wäre das VideoDrawing nur ein Entwurf eines “Bildes”, sowas wie ein Bauplan, in diesem Fall ein ablaufendes Video. Die DrawingBrush sorgt dafür dass dieser Entwurf auch sichtbar gemacht wird, und der Entwurf (der Bauplan des Bildes) in ein “Bild” umgesetzt wird. [drawingBrush.Drawing = Videobackground]

Mit dem Befehl Opacity können Sie der DrawingBrush eine Durchsichtigkeit zuweisen (in diesem Falle 0.7 was bedeutet dass Sie 70% Deckkraft hat und 30% Durchlässigkeit).

Nun muss der MediaPlayer das Video nur noch abspielen [myVideoPlayer.Play].

Die DrawingBrush können wir JEDEM Steuerelement mit Content-Eigenschaft zuweisen. Ob es jetzt ein Button, eine Ellipse, ein Textblock oder eine TextBox ist. Die Wahl des Steuerelementes spielt keine Rolle, das Video wird immer im Hintergrund abgespielt.

Dim VideoButton As New Button
VideoButton.Height = 300
VideoButton.Width = 300
VideoButton.Background = DrawingBrush

Wir instanzieren einen neuen Button mit den Größenabmessungen 300x300 und weisen seinem Background die DrawingBrush zu. In seinem Hintergrund wird sich das Video abspielen. (Vergessen Sie nicht dem Elternelement des Buttons (dem Grid) den Button als Kind zuzuweisen, um ihn sichtbar zu machen).

Sie sehen dass diese wenigen Zeilen Code bereits einen Button mit Videohintergrund entwerfen.

Nun spielt sich im Hintergrund des Buttons das Video ab. Jedoch nur einmal! Um das Video zu wiederholen, müssen wir einen Umweg gehen, bzw. den MediaPlayer erweitern.

'Neue TimeLine instanzieren und die VideoURI übergeben (in diesem Fall aus dem Internet)
       Dim TimeLine as New MediaTimeline(New Uri(http://shralp.com/sendung/shralp132.wmv,_  UriKind.RelativeOrAbsolute))
       'Der TimeLine vorgeben das Video immer zu wiederholen
       TimeLine.RepeatBehavior = Animation.RepeatBehavior.Forever
       'Vorgeben wie die TimeLine sich nach erreichen des Videoendes verhält
       TimeLine.FillBehavior = Animation.FillBehavior.Stop

       'Neue MediaClock aus der TimeLine erstellen um diese dem MediaPlayer zuzuweisen
       Dim mClock As MediaClock = TimeLine.CreateClock

myvideoPlayer = New MediaPlayer
       myvideoPlayer.Clock = mClock
       'Sound wegnehmen
       myvideoPlayer.IsMuted = True

       ' VideoHintergrundzeichnung  erstellen.
       Dim Videobackground As New VideoDrawing
       'Abspielfläche des Hintergrundes bestimmen
       Videobackground.Rect = New Rect(0, 0, container.Width, container.Height)
       'Der Videohintergrundzeichnung den Videoplayer zuweisen
       Videobackground.Player = myvideoPlayer

'Neue Hintergrundzeichnugn erstellen für die container.Fill Eigenschaft (den Hintergrund der Uhr)
       Dim drawingBrush As New DrawingBrush
       'Durchsichtigkeit = 30%
       drawingBrush.Opacity = 0.7
       'Die Videohintergrundzeichnung der Hintergrundzeichnugn zuzuweisen
       drawingBrush.Drawing = Videobackground

Den unteren Teil kennen Sie, er ist identisch wie im vorherigen Codeauszug. Was hat sich nun geändert? Die Videoadresse (URI) wird nicht mehr dem MediaPlayer übergeben, sondern einer instanziierten TimeLine die sich die Videoadresse und gleichzeitig auch die Länge merkt . Sie kümmert sich auch um das Wiederholungsverhalten [TimeLine.RepeatBehavior = Animation.RepeatBehavior.Forever]. Das Video wird nun wiederholt.

Aus der TimeLine erstellen wir eine MediaClock, die quasi wie ein Zeitbeauftragter die Vermittlungsstelle zwischen dem MediaPlayer und der TimeLine darstellt und die aus den Informationen der TimeLine erstellt wird. [Dim mClock As MediaClock = TimeLine.CreateClock ]. Diese MediaClock wird nun ihrerseits dem MediaPlayer bekannt gemacht und übergeben, der durch sie nun an die Informationen für die Videoadresse, die Länge und das Wiederholungsverhalten gekommen ist, und sich dementsprechend “verhält”. [myvideoPlayer.Clock = mClock]

Der MediaPlayer muss nicht gestartet werden. Der Befehl myvideoPlayer.Play entfällt. Er wird intern durch die TimeLine übernommen.

Der MediaPlayer ist des Weiteren stumm geschaltet worden, da eine sich ewig wiederholende Hintergrundmusik des Videos auf die Dauer doch etwas nervt. Finde ich.

[myvideoPlayer.IsMuted = True]

Das Resultat ist ein sich wiederholender Videohintergrund, der, ich sag es noch einmal, ALLEN Steuerelementen mit Conten Eigenschaft zugewiesen werden kann.

Nun soll die Uhr gebaut werden, in der der Videohintergrund sich abspielen soll. In einem neuen WPF – Projekt, dass sie in Visual Studio angelegt haben, sehen Sie im rechts im Projektmappen Explorer dem Projekt untergeordnet die XAML-Dateien Application.xaml und Window1.xaml. Application.xaml verwaltet die Applikation, wohingegen Window1.xaml das Startfenster der Applikation darstellt. Das Startfenster beispielsweise können Sie folglich in der CodeBehind Datei von Application.xaml --> Application.xaml.vb im Konstruktor der Applikation einstellen. Window1 soll jedoch in diesem Falle Startfenster bleiben.

Doppelklicken Sie im ProjektmappenExplorer auf Window1.xaml und fügen Sie im Window Tag den folgenden Code ein: AllowsTransparency="True" WindowStyle="None", sodass Sie folgenden Code erhalten:

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" AllowsTransparency="True" WindowStyle="None">

Die Befehle AllowsTransparency=True und WindowStyle=None gehen immer Hand in Hand. AllowsTransparency legt fest, ob das Fenster transparent sein darf oder nicht, und sollte es transparent sein dürfen (also AllowsTransparency=”True”), dann ist der einzig mögliche Wert für “WindowStyle” (welcher das Aussehen des Fensters bzw. des Fensterrahmen festlegt) die Möglichkeit “None”. Das Fenster hat nämlich kein Aussehen, da es nicht sichtbar ist, und nur der Inhalt angezeigt wird. Nun müssen Sie nur noch den Hintergrund des Fensters auf transparent setzen indem sie auch diesen Befehl hinzufügen: Background="Transparent" , und das Fenster ist bis auf die Kindelemente völlig unsichtbar.

Doppelklicken Sie nun im ProjektmappenExplorer auf die Datei Window1.xaml.vb und schreiben Sie unter Class Window1 die CodeZeile “Sub New” und drücken Sie Enter. Visual Studio zeigt nun den Konstruktor an. Nach dem Befehl Initialize Components, der die dem Fenster (Window1) untergeordneten Kindelemente initialisiert, schreiben Sie nun folgenden (fettgedruckten) Code:

Class Window1
    Sub New()

        ' Dieser Aufruf ist für den Windows Form-Designer erforderlich.
        InitializeComponent()

        ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
   Me.Topmost = True
        Me.ShowInTaskbar = False
    End Sub

End Class

Durch diese beiden Befehle erreichen wir

1. dass das Fenster immer als oberstes Element auf dem Desktop ist (Topmost=True) und

2. dass das Fenster nicht in der Taskbar angezeigt wird  (ShowInTaskbar=False”)

Wechseln Sie nun wieder in den XAML Code des Fensters und fügen Sie dem Grid (welches als Container für alle anderen im Fenster beinhalteten Steuerelemente dient) einen Loaded-Eventhandler hinzu, indem Sie den Befehl Loaded=”” tippen und den von IntelliSense gemachten Vorschlag <NeuerEreignishandler> dankbar annehmen. Geben Sie dem Grid weiterhin einen Namen, in dem Falle “gridClock”, indem Sie im GridTag den Befehl Name=”gridClock” einfügen. In der CodeBehind-Datei finden Sie nun den folgenden Routinenrumpf des LoadedEreignis:

Private Sub Grid_Loaded(ByVal sender As System.Object, ByVal e As _ System.Windows.RoutedEventArgs)

End Sub

Hier hinterlegen wir die Befehle zum Malen der BasisUhr. Wir rufen der besseren Struktur und schöneren Lesbarkeit halber die Befehle in einer Methode gekapselt auf. Schreiben Sie in den Methodenrumpf: “Uhrmalen()”

Ignorieren Sie die von VisualStudio malerisch kreierte Schlängelei unter dem Methodenaufruf und stellen Sie VisualStudio zufrieden, indem sie eine neue Methode mit dem Namen "Uhrmalen” einfügen:

Private Sub Grid_Loaded(ByVal sender As System.Object, ByVal e As _  System.Windows.RoutedEventArgs)
      Uhrmalen()
End Sub

Private Sub Uhrmalen()

End Sub

Die Methode Uhrmalen soll einen Kreis, die Zeiger und den Hintergrund zeichnen. Dafür müssen vorher noch einige Variablen deklariert werden, die Deklaration erfolgt  global um die Applikation nachher um Features wie “Größe – und/oder Video ändern” erweitern zu können, bzw. um die Zeigerpositionen in der dafür vorgesehenen Funktion anzupassen. Wir können auf die Variablen somit im gesamten Bereich zugreifen und diese dann gegebenenfalls in entsprechenden Methoden ändern.

Private container As Ellipse
Private Minutenzeiger As New Line

Die Ellipse wird als “Container” genutzt, sie bekommt den Videohintergrund zugewiesen und in ihr wird das Ziffernblatt gemalt und werden auch die Zeiger positioniert.

'Der Uhr Container ist eine neue Ellipse
     container = New Ellipse
     'Die Höhe ist die Fensterhöhe und die Breite ist die Fensterbreite
     container.Height = Me.Height - 5
     container.Width = Me.Width - 5 
    'Die Durchsichtigkeit wird festgelegt
     container.Opacity = myOpacity

gridClock.Children.Add(container)

Das Zeichnen der Zeiger bzw des Ziffernblattes erfolgt auf der Basis von sogenannten PolarKoordinaten. In einem PolarKoordinatensystem wird die Position eines Punktes nicht wie gewohnt durch x- bzw. y- Werte angegeben, sondern durch einen Winkel (zwischen dem Ursprung des Koordinatensystems und der positiven x-Achse) und einer Länge der Strecke s zum Punkt P. Durch dieses Koordinatensystem lässt sich beispielsweise ein Kreis wunderbar darstellen. Bleibt die Länge s immer gleich während der Winkel sich ändert, wird der Effekt erzeugt den sie manuell mit einem Faden erreichen, den sie mit einem Finger am oberen Ende festhalten und mit der Hand am unteren Ende um 360Grad weiterführen. Wir erhalten einen Kreis. Dieses zählt neben der Technik des “Prickelns” wohl zu den am häufigsten im Kindergarten gemachten Erlebnisse.

Das Polarkoordinatensystem wird in diesem Falle genutzt um die Werte für die Zeigerpositionierung, bzw. die des Ziffernblattes zu berechnen, denn:  Durch den Winkel und die Länge der Strecke s können wir wiederum durch die sinus- bzw. die cosinus-Formel und den Satz des Phythagoras (wer kennt ihn nicht, den Guten..) berechnen, wo sich der Punkt P befindet, welchen wir zur Darstellung unserer Uhr für den Computer in x- bzw. y-Werten angegeben brauchen.

Die PolarkoordinatenKlasse finden Sie als CodeDatei im Anhang zum Downloaden. Rechtsklicken Sie im ProjektmappenExplorer auf das Projekt und wählen Sie die Befehle Hinzufügen und folgend vorhandenes Element um die Klasse auszuwählen, und mit dem Klick auf Hinzufügen dem Projekt bereitzustellen. Sie können sie nutzen, indem ihr beim Aufruf die Werte des KoordinatenUhrsprungs, der Streckenbreite, der Streckenhöhe und den Winkel übergeben werden.

Dim locPcStart As New PolarCoordinate(locMitte, container.Width / 2 - 20, container.Height / 2 - 20, locWinkel)

locMitte ist die Mitte der Ellipse die als Uhrcontainer dient, die Streckenbreite ist die Hälfte der Breite des Uhrcontainers minus 20 Pixel, die Streckenhöhe ist die Hälfte der Höhe des Uhrcontainers minus 20 Pixel und der vorher berechnete Winkel (die 360 Grad eines Kreises werden für das Ziffernblatt mit 12 Zeichen durch 12 geteilt und das Ergebnis (30) schrittweise abgegangen) ist in diesem Falle durch die Variable locWinkel abgedeckt.

Zurück kriegen wir von der PolarCoordinate Klasse die x-  und y-Werte des errechneten Punktes. Abgerufen werden sie wie folgt:

locPcStart.Cartesian.X und locPcStart.Cartesian.Y

Damit sind sie zur Weiterverwendung für die zu malenden Linien nutzbar, die uns als Ziffernblatt dienen sollen.

Den vollständigen Code können Sie wie oben bereits erwähnt herunter laden und einsehen. Lassen Sie uns (uns) im Folgenden exemplarisch auf das Zeichnen des Minutenzeigers konzentrieren. Wir initialisieren ihn in der Routine Uhrmalen, seine Position und Größe wird jedoch erst in der Routine Uhrzeigermalen() bestimmt. 

'Minutenzeiger
      Minutenzeiger.Stroke = Brushes.Silver
      Minutenzeiger.StrokeThickness = 3
      gridClock.Children.Add(Minutenzeiger)

Somit haben wir der Linie mit dem Namen “Minutenzeiger” die Farbe Silver zugewiesen und eine Breite von 3. Sie ist sichtbar, da sie dem Grid als Kindelement hinzugefügt wird.

So weit, so gut. Nun braucht die Uhr eine Funktion die ihr jede Sekunde eine neue Zeigerposition zuweist.

Die Applikation braucht einen Aufpasser der jede Sekunde eine Methode aufruft die dieses übernimmt. Und wer wäre dafür geeigneter als ein Timer. Lassen Sie uns im Folgenden einen solchen in die Grid_Loaded Methode einfügen.

Private Sub Grid_Loaded(ByVal sender As System.Object, ByVal e As _  System.Windows.RoutedEventArgs)
     Uhrmalen()
'Timerüberwachung zur Uhrzeigeraktualisierung
     'Neuen timer hinzufügen
     Dim ticker As New System.Windows.Threading.DispatcherTimer()
     ticker.Interval = New TimeSpan(1000)
'Wenn Zeitraum (1000ms) vorbei ist: Uhrzeigermalen aufrufen
     AddHandler ticker.Tick, AddressOf Uhrzeigermalen
    'Timer starten
     ticker.Start()
End Sub

Nun haben wir einen Timer der nach Ablauf von 1000 Milisekunden (entspricht 1 Sekunde), die Methode Uhrzeigermalen aufruft. Nun meckert VisualStudio die Methode Uhrzeigermalen zu Recht an, da diese noch nicht existiert. Deswegen soll sie im nächsten Schritt eingefügt werden. In der Methode Uhrzeigermalen werden die Zeiger der Uhr richtig positioniert, der Uhrzeit entsprechend eben.

Private Sub Uhrzeigermalen()

'Zeiger malen

'Parameter für Minutenzeiger
      Dim locMinutenZeigerWinkel As Single = Date.Now.Minute
      locMinutenZeigerWinkel *= 6
      locMinutenZeigerWinkel –= 90

  'Minutenzeiger malen
      locZeigerStart = New PolarCoordinate(locMitte, 0, 0, locMinutenZeigerWinkel)
      locZeigerEnde = New PolarCoordinate(locMitte, container.Width / 2 - 15, container.Height / 2 - 15, locMinutenZeigerWinkel)

      Minutenzeiger.X1 = locZeigerStart.Cartesian.X
      Minutenzeiger.Y1 = locZeigerStart.Cartesian.Y
      Minutenzeiger.X2 = locZeigerEnde.Cartesian.X
      Minutenzeiger.Y2 = locZeigerEnde.Cartesian.Y

(...Zeichnen der anderen Zeiger hier nicht aufgeführt)

End Sub

Schlussendlich fehlt nur noch die Zuweisung des Videohintergrunds an den Uhrcontainer (die Ellipse). Und wie Sie wissen, funktioniert das ganz einfach. Wir benutzen den obigen Code und weisen die geschaffene DrawingBrush einfach der Ellipse als Hintergrund zu. [container.Fill = drawingBrush]

Bleibt mir nur noch viel Spaß beim Experimentieren zu wünschen,  und ihrem Desktop aufregende Zeiten mit ihrer WPF Anwendung.

VideoUhr.rar (71,31 kb)

Tags: , , , , ,

Kommentare

08.05.2010 14:20:37 #

Mariana

I was very pleased to find this site.I wanted to thank you for this great read!! I definitely enjoying every little bit of it and I have you bookmarked to check out new stuff you post.

Mariana Vereinigte Staaten von Amerika

17.05.2010 21:26:02 #

ab circle pro

Igood info
regards

ab circle pro Vereinigte Staaten von Amerika

18.05.2010 02:54:03 #

cash advance

Found your site on del.icio.us today and really liked it.. i bookmarked it and will be back to check it out some more later ..

cash advance Vereinigte Staaten von Amerika

19.05.2010 07:33:36 #

loan online payday quick

Valuable information and excellent design you got here! I would like to thank you for sharing your thoughts and time into the stuff you post!! Thumbs up!

loan online payday quick Vereinigte Staaten von Amerika

20.05.2010 00:05:23 #

Wahdo

If you have to do it, you might as well do it right.

Wahdo Vereinigte Staaten von Amerika

21.06.2010 13:50:27 #

Hot Headlines

Would it be cool to provide some more info on this in the future? Thanks

Hot Headlines Vereinigte Staaten von Amerika

25.06.2010 11:37:42 #

vaniqa

danke fur die info bruder

vaniqa Deutschland

02.07.2010 19:06:55 #

La Martina

Interessant zu lesen, thanks for sharing, toller Job auf dem Blog. Sie scheinen ein großer Blogger werden.

La Martina Vereinigte Staaten von Amerika

09.07.2010 10:08:45 #

chanel

After reading the article, I feel that I need more information on the topic. Can you suggest some resources please?

chanel Norwegen

Kommentar schreiben




  Country flag

biuquote
  • Kommentar
  • Live Vorschau
Loading



Powered by BlogEngine.NET 1.5.0.7
Theme by Mads Kristensen