Freigeben über


Übersicht über das WPF-Grafikrendering

Dieses Thema enthält eine Übersicht über die visuelle Ebene von WPF. Der Schwerpunkt liegt dabei auf der Rolle der Visual-Klasse für die Renderingunterstützung im WPF-Modell.

Dieses Thema enthält folgende Abschnitte.

  • Rolle des visuellen Objekts
  • So werden visuelle Objekte zum Erstellen von Steuerelementen verwendet
  • Visuelle Struktur
  • Visuelles Renderingverhalten
  • VisualTreeHelper-Klasse
  • Verwandte Abschnitte

Rolle des visuellen Objekts

Die Visual-Klasse ist die grundlegende Abstraktion, von der jedes FrameworkElement-Objekt abgeleitet ist. Sie dient außerdem als Einstiegspunkt zum Schreiben neuer Steuerelemente in WPF, und in Vielem kann sie als das Fensterhandle (HWND) im Win32-Anwendungsmodell betrachtet werden.

Das Visual-Objekt ist ein zentrales WPF-Objekt, dessen primäre Rolle die Unterstützung des Rendering ist. Steuerelemente der Benutzeroberfläche, wie Button und TextBox, werden von der Visual-Klasse abgeleitet und verwenden diese zum Beibehalten ihrer Renderingdaten. Das Visual-Objekt unterstützt folgende Vorgänge:

  • Ausgabeanzeige: Rendern des beibehaltenen, serialisierten Zeichnungsinhalts eines visuellen Objekts.

  • Transformationen: Ausführen von Transformationen für ein visuelles Element.

  • Clipping: Bereitstellen von Clippingbereichunterstützung für ein visuelles Objekt.

  • Treffertests: Bestimmen, ob eine Koordinate oder eine Geometrie innerhalb der Grenzen eines visuellen Objekts enthalten ist.

  • Berechnungen für umgebende Felder: Bestimmen des umgebenden Rechtecks eines visuellen Objekts.

Das Visual-Objekt umfasst jedoch keine Unterstützung für Features außerhalb des Rendering, z. B.:

  • Ereignisbehandlung

  • Layout

  • Formate

  • Datenbindung

  • Globalisierung

Visual wird als öffentliche abstrakte Klasse verfügbar gemacht, von der untergeordnete Klassen abgeleitet werden müssen. Die folgende Abbildung zeigt die Hierarchie der visuellen Objekte, die in WPF verfügbar gemacht werden.

Hierarchie der Visual-Klasse

Diagramm der vom Visual-Objekt abgeleiteten Klassen

DrawingVisual-Klasse

DrawingVisual ist eine einfache Zeichnungsklasse, die verwendet wird, um Formen, Bilder oder Text zu rendern. Diese Klasse wird als einfach angesehen, weil sie weder Layout noch Ereignisbehandlung bereitstellt. Dadurch wird die Laufzeitleistung gesteigert. Aus diesem Grund sind Zeichnungen ideal für Hintergründe und ClipArt. DrawingVisual kann verwendet werden, um ein benutzerdefiniertes visuelles Objekt zu erstellen. Weitere Informationen finden Sie unter Verwenden von DrawingVisual-Objekten.

Viewport3DVisual-Klasse

Viewport3DVisual bildet eine Brücke zwischen Visual-2D-Objekten und Visual3D-Objekten. Die Visual3D-Klasse ist die Basisklasse für alle visuellen 3D-Elemente. Für Viewport3DVisual müssen ein Camera-Wert und ein Viewport-Wert definiert werden. Die Kamera ermöglicht Ihnen die Anzeige der Szene. Der Viewport legt fest, wo die Projektion auf die 2D-Oberfläche abgebildet wird. Weitere Informationen über 3D in WPF finden Sie unter Übersicht über 3D-Grafiken.

ContainerVisual-Klasse

Die ContainerVisual-Klasse wird als Container für eine Auflistung von Visual-Objekten verwendet. Die DrawingVisual-Klasse wird aus der ContainerVisual-Klasse abgeleitet, womit sie eine Auflistung von visuellen Objekten enthalten kann.

Zeichnungsinhalt in visuellen Objekten

Ein Visual-Objekt speichert seine Renderingdaten als Anweisungsliste für Vektorgrafiken. Jedes Element in der Anweisungsliste stellt einen Low-Level-Satz mit Grafikdaten und dazugehörigen Ressourcen in einem serialisierten Format dar. Es gibt vier verschiedene Typen von Renderingdaten, die Zeichnungsinhalt enthalten können.

Zeichnungsinhaltstyp

Beschreibung

Vektorgrafik

Stellt Vektorgrafikdaten und dazugehörige Brush-Informationen und Pen-Informationen dar.

Bild

Stellt ein Bild innerhalb eines von einer Rect-Struktur definierten Bereichs dar.

Symbol

Stellt eine Zeichnung dar, die eine als GlyphRun bezeichnete Symbolfolge aus einer angegebenen Schriftartressource rendert. Auf diese Weise wird Text dargestellt.

Video

Stellt eine Zeichnung dar, die Video rendert.

Mit DrawingContext können Sie ein Visual-Objekt mit visuellem Inhalt auffüllen. Wenn Sie die Zeichnungsbefehle eines DrawingContext-Objekts verwenden, speichern Sie einen Satz von Renderingdaten, die später vom Grafiksystem verwendet werden. Sie zeichnen nicht in Echtzeit auf dem Bildschirm.

Wenn Sie ein WPF-Steuerelement, z. B. ein Button-Steuerelement, erstellen, generiert es implizit Renderingdaten für die eigene Darstellung. Wenn Sie z. B. die Content-Eigenschaft des Button-Steuerelements festlegen, wird es zur Speicherung einer Renderingdarstellung eines Symbols veranlasst.

Ein Visual beschreibt den eigenen Inhalt als ein oder mehrere Drawing-Objekte, die in einer DrawingGroup enthalten sind. Eine DrawingGroup beschreibt außerdem Durchlässigkeitsmasken, Transformationen, Bitmapeffekte und andere Vorgänge, die auf ihre Inhalte angewendet werden. DrawingGroup-Vorgänge werden beim Rendering von Inhalt in der folgenden Reihenfolge angewendet: OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSet und dann Transform.

Die folgende Abbildung zeigt die Reihenfolge, in der DrawingGroup-Vorgänge während der Renderingsequenz angewendet werden.

Reihenfolge von DrawingGroup-Vorgängen

DrawingGroup-Reihenfolge der Vorgänge

Weitere Informationen finden Sie unter Übersicht über Zeichnungsobjekte.

Zeichnungsinhalt auf der Visual-Ebene

Ein DrawingContext wird niemals direkt instanziiert. Sie können jedoch mit bestimmten Methoden, z. B. DrawingGroup.Open und DrawingVisual.RenderOpen, einen Zeichnungskontext abrufen. Im folgenden Beispiel wird ein DrawingContext aus einem DrawingVisual abgerufen und zum Zeichnen eines Rechtecks verwendet.

        ' Create a DrawingVisual that contains a rectangle.
        Private Function CreateDrawingVisualRectangle() As DrawingVisual
            Dim drawingVisual As New DrawingVisual()

            ' Retrieve the DrawingContext in order to create new drawing content.
            Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()

            ' Create a rectangle and draw it in the DrawingContext.
            Dim rect As New Rect(New Point(160, 100), New Size(320, 80))
            drawingContext.DrawRectangle(Brushes.LightBlue, CType(Nothing, Pen), rect)

            ' Persist the drawing content.
            drawingContext.Close()

            Return drawingVisual
        End Function
// Create a DrawingVisual that contains a rectangle.
private DrawingVisual CreateDrawingVisualRectangle()
{
    DrawingVisual drawingVisual = new DrawingVisual();

    // Retrieve the DrawingContext in order to create new drawing content.
    DrawingContext drawingContext = drawingVisual.RenderOpen();

    // Create a rectangle and draw it in the DrawingContext.
    Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80));
    drawingContext.DrawRectangle(System.Windows.Media.Brushes.LightBlue, (System.Windows.Media.Pen)null, rect);

    // Persist the drawing content.
    drawingContext.Close();

    return drawingVisual;
}

Auflisten von Zeichnungsinhalt auf der Visual-Ebene

Neben ihren anderen Verwendungszwecken stellen die Drawing-Objekte auch ein Objektmodell für die Auflistung eines Visual bereit.

HinweisHinweis

Wenn Sie den Visualinhalt auflisten, rufen Sie Drawing-Objekte ab, und nicht die zugrunde liegende Darstellung der Renderingdaten als Anweisungsliste für Vektorgrafiken.

Im folgenden Beispiel wird die GetDrawing-Methode verwendet, um den DrawingGroup-Wert eines Visual abzurufen und aufzulisten.

public void RetrieveDrawing(Visual v)
{
    DrawingGroup dGroup = VisualTreeHelper.GetDrawing(v);
    EnumDrawingGroup(dGroup);

}

 // Enumerate the drawings in the DrawingGroup.
 public void EnumDrawingGroup(DrawingGroup drawingGroup)
 {
     DrawingCollection dc = drawingGroup.Children;

     // Enumerate the drawings in the DrawingCollection.
     foreach (Drawing drawing in dc)
     {
         // If the drawing is a DrawingGroup, call the function recursively.
         if (drawing.GetType() == typeof(DrawingGroup))
         {
             EnumDrawingGroup((DrawingGroup)drawing);
         }
         else if (drawing.GetType() == typeof(GeometryDrawing))
         {
             // Perform action based on drawing type.  
         }
         else if (drawing.GetType() == typeof(ImageDrawing))
         {
             // Perform action based on drawing type.
         }
         else if (drawing.GetType() == typeof(GlyphRunDrawing))
         {
             // Perform action based on drawing type.
         }
         else if (drawing.GetType() == typeof(VideoDrawing))
         {
             // Perform action based on drawing type.
         }
     }
 }

So werden visuelle Objekte zum Erstellen von Steuerelementen verwendet

Viele Objekte in WPF bestehen aus anderen visuellen Objekten, d. h., sie können unterschiedliche Hierarchien von Nachfolgerobjekten enthalten. Zahlreiche Benutzeroberflächenelemente in WPF, z. B. Steuerelemente, bestehen aus mehreren visuellen Objekten, die verschiedene Typen von Renderingelementen darstellen. Zum Beispiel kann das Button-Steuerelement eine Anzahl anderer Objekte enthalten, einschließlich ClassicBorderDecorator, ContentPresenter und TextBlock.

Der folgende Code zeigt ein in Markup definiertes Button-Steuerelement.

<Button Click="OnClick">OK</Button>

Wenn Sie die visuellen Objekte auflisten sollten, aus denen das Button-Standardsteuerelement besteht, würden Sie die nachfolgend dargestellte Hierarchie der visuellen Objekte vorfinden:

Diagramm der Hierarchie der visuellen Struktur

Diagramm der visuellen Strukturhierarchie

Das Button-Steuerelement enthält ein ClassicBorderDecorator-Element, das wiederum ein ContentPresenter-Element enthält. Das ClassicBorderDecorator-Element ist dafür verantwortlich, einen Rahmen und einen Hintergrund für das Button-Steuerelement zu zeichnen. Das ContentPresenter-Element ist dafür verantwortlich, den Inhalt des Button-Steuerelements anzuzeigen. Da Sie Text anzeigen, enthält das ContentPresenter-Element in diesem Fall ein TextBlock-Element. Der Umstand, dass das Button-Steuerelement ein ContentPresenter-Element verwendet, bedeutet, dass der Inhalt durch andere Elemente dargestellt werden könnte, z. B. ein Image oder eine Geometrie, z. B. eine EllipseGeometry.

Steuerelementvorlagen

Der Schlüssel zur Erweiterung eines Steuerelements in eine Hierarchie von Steuerelementen ist die ControlTemplate. Eine Steuerelementvorlage gibt die visuelle Standardhierarchie für ein Steuerelement an. Wenn Sie ein Steuerelement explizit mit Verweisen versehen, versehen Sie seine visuelle Hierarchie implizit mit Verweisen. Sie können die Standardwerte für eine Steuerelementvorlage überschreiben, um eine angepasste visuelle Darstellung für ein Steuerelement zu erstellen. Sie könnten z. B. den Hintergrundfarbwert des Button-Steuerelements so ändern, dass es einen Wert für einen linearen Farbverlauf statt eines Werts für eine Volltonfarbe verwendet. Weitere Informationen hierzu finden Sie unter Button-Stile und -Vorlagen.

Ein Element der Benutzeroberfläche, z. B. ein Button-Steuerelement, enthält mehrere Anweisungslisten für Vektorgrafiken, die die gesamte Renderingdefinition eines Steuerelements beschreiben. Der folgende Code zeigt ein in Markup definiertes Button-Steuerelement.

<Button Click="OnClick">
  <Image Source="images\greenlight.jpg"></Image>
</Button>

Wenn Sie die visuellen Objekte und die Anweisungslisten für Vektorgrafiken auflisten sollten, aus denen das Button-Standardsteuerelement besteht, würden Sie die nachfolgend dargestellte Hierarchie der visuellen Objekte vorfinden:

Diagramm der visuellen Struktur und der Renderingdaten

Diagramm der visuellen Struktur und des Renderings von Daten

Das Button-Steuerelement enthält ein ClassicBorderDecorator-Element, das wiederum ein ContentPresenter-Element enthält. Das ClassicBorderDecorator-Element ist dafür verantwortlich, alle diskreten Grafikelemente zu zeichnen, aus denen der Rahmen und der Hintergrund einer Schaltfläche bestehen. Das ContentPresenter-Element ist dafür verantwortlich, den Inhalt des Button-Steuerelements anzuzeigen. Da Sie ein Bild anzeigen, enthält das ContentPresenter-Element in diesem Fall ein Image-Element.

Im Zusammenhang mit der Hierarchie von visuellen Objekten und Anweisungslisten für Vektorgrafiken sind ein paar Punkte zu beachten:

  • Die Reihenfolge in der Hierarchie stellt die Renderingreihenfolge der Zeichnungsinformationen dar. Vom visuellen Stammelement werden untergeordnete Elemente von links nach rechts und von oben nach unten traversiert. Wenn ein Element über visuelle untergeordnete Elemente verfügt, werden sie vor den Geschwistern des Elements traversiert.

  • Elemente in der Hierarchie, die keine Blattknoten sind, z. B. ContentPresenter, werden für die Aufnahme von untergeordneten Elementen verwendet. Sie enthalten keine Anweisungslisten.

  • Wenn ein visuelles Element sowohl eine Anweisungsliste für Vektorgrafiken als auch untergeordnete visuelle Elemente enthält, wird die Anweisungsliste im übergeordneten visuellen Element vor Zeichnungen in einem der untergeordneten visuellen Objekte gerendert.

  • Die Elemente in der Anweisungsliste für Vektorgrafiken werden von links nach rechts gerendert.

Visuelle Struktur

Die visuelle Struktur enthält alle visuellen Elemente, die in der Benutzeroberfläche einer Anwendung verwendet werden. Da ein visuelles Element beibehaltene Zeichnungsinformationen enthält, können Sie sich die visuelle Struktur als ein Szenendiagramm vorstellen, das alle Renderinginformationen enthält, die zum Zusammensetzen der Ausgabe für das Anzeigegerät benötigt werden. Diese Struktur ist die Ansammlung aller visuellen Elemente, die direkt von der Anwendung erstellt werden, ob in Code oder Markup. Die visuelle Struktur enthält außerdem alle visuellen Elemente, die von der Vorlagenerweiterung von Elementen wie Steuerelementen und Datenobjekten erstellt werden.

Der folgende Code zeigt ein in Markup definiertes StackPanel-Element.

<StackPanel>
  <Label>User name:</Label>
  <TextBox />
  <Button Click="OnClick">OK</Button>
</StackPanel>

Wenn Sie die visuellen Objekte auflisten sollten, aus denen das StackPanel-Element im Markupbeispiel besteht, würden Sie die nachfolgend dargestellte Hierarchie der visuellen Objekte vorfinden:

Diagramm der Hierarchie der visuellen Struktur

Diagramm der visuellen Strukturhierarchie

Renderingreihenfolge

Die visuelle Struktur bestimmt die Renderingreihenfolge von visuellen Objekten und Zeichnungsobjekten in WPF. Die Traversierreihenfolge beginnt mit dem visuellen Stammelement, dem obersten Knoten in der visuellen Struktur. Anschließend werden die untergeordneten Elemente des visuellen Stammelements von links nach rechts traversiert. Wenn ein visuelles Objekt untergeordnete Elemente hat, werden diese vor den Geschwistern des visuellen Objekts traversiert. Das heißt, dass der Inhalt eines untergeordneten visuellen Elements vor dem Inhalt des visuellen Objekts selbst gerendert wird.

Diagramm der Renderingreihenfolge der visuellen Struktur

Diagramm der visuellen Struktur-Rendering-Reihenfolge

Visuelles Stammelement

Das visuelle Stammelement ist das oberste Element in der Hierarchie einer visuellen Struktur. In den meisten Anwendungen ist die Basisklasse des visuellen Stammelements entweder Window oder NavigationWindow. Wenn Sie aber visuelle Objekte in einer Win32-Anwendung hosten würden, wäre das visuelle Stammelement das oberste im Win32-Fenster gehostete visuelle Objekt. Weitere Informationen hierzu finden Sie unter Lernprogramm: Hosten von visuellen Objekten in einer Win32-Anwendung.

Beziehung zur logischen Struktur

Die logische Struktur in WPF stellt die Elemente einer Anwendung zur Laufzeit dar. Auch wenn Sie diese Struktur nicht direkt ändern, ist diese Ansicht der Anwendung hilfreich, um Eigenschaftenvererbung und Ereignisrouting zu verstehen. Im Gegensatz zur visuellen Struktur kann die logische Struktur nicht visuelle Datenobjekte, z. B. ListItem, darstellen. In vielen Fällen sind die logische Struktur und die Markupdefinitionen einer Anwendung nahezu deckungsgleich. Der folgende Code zeigt ein in Markup definiertes DockPanel-Element.

<DockPanel>
  <ListBox>
    <ListBoxItem>Dog</ListBoxItem>
    <ListBoxItem>Cat</ListBoxItem>
    <ListBoxItem>Fish</ListBoxItem>
  </ListBox>
  <Button Click="OnClick">OK</Button>
</DockPanel>

Wenn Sie die logischen Objekte auflisten sollten, aus denen das DockPanel-Element im Markupbeispiel besteht, würden Sie die nachfolgend dargestellte Hierarchie der logischen Objekte vorfinden:

Diagramm der logischen Struktur

Baumstrukturdiagramm

Die visuelle Struktur und die logische Struktur werden mit dem aktuellen Satz der Anwendungselemente synchronisiert und spiegeln so jede Aufnahme, Löschung oder Änderung eines Elements wider. Die Strukturen liefern aber verschiedene Ansichten der Anwendung. Im Gegensatz zur visuellen Struktur erweitert die logische Struktur nicht das ContentPresenter-Element eines Steuerelements. Das heißt, es gibt für denselben Objektsatz keine direkte 1:1-Entsprechung zwischen einer logischen Struktur und einer visuellen Struktur. Wenn für das LogicalTreeHelper-Objekt die GetChildren-Methode und für das VisualTreeHelper-Objekt die GetChild-Methode aufgerufen und dasselbe Element als Parameter verwendet wird, führt dies sogar zu unterschiedlichen Ergebnissen.

Weitere Informationen über die logische Struktur finden Sie unter Strukturen in WPF.

Anzeigen der visuellen Struktur mit XamlPad

Das WPF-Tool XamlPad ermöglicht das Anzeigen und Durchsuchen der visuellen Struktur, die dem aktuell definierten XAML-Inhalt entspricht. Klicken Sie auf der Menüleiste auf die Schaltfläche Visuelle Struktur anzeigen, um die visuelle Struktur anzuzeigen. Die folgende Abbildung zeigt die Erweiterung des XAML-Inhalts in die Knoten der visuellen Struktur im Bereich Visual Tree Explorer von XamlPad:

Bereich Visual Tree Explorer in XamlPad

Visueller Struktur-Explorer-Bereich in XamlPad

Beachten Sie, dass die Steuerelemente Label, TextBox und Button jeweils eine eigene Hierarchie der visuellen Objekte im Bereich Visual Tree Explorer von XamlPad anzeigen. Das liegt daran, dass WPF-Steuerelemente über eine ControlTemplate verfügen, die die visuelle Struktur dieses Steuerelements enthält. Wenn Sie ein Steuerelement explizit mit Verweisen versehen, versehen Sie seine visuelle Hierarchie implizit mit Verweisen.

Erstellen von visuellen Leistungsprofilen

WPF stellt eine Suite von Tools zum Erstellen von Leistungsprofilen bereit, mit denen Sie das Laufzeitverhalten einer Anwendung analysieren und die Typen der anwendbaren Leistungsoptimierungen bestimmen können. Das Tool Visual Profiler bietet eine umfangreiche grafische Ansicht der Leistungsdaten. Dazu wird eine direkte Zuordnung zur visuellen Struktur der Anwendung vorgenommen. In dieser Bildschirmaufnahme enthält der Abschnitt CPU-Verwendung von Visual Profiler eine genaue Aufschlüsselung der Nutzung von WPF-Diensten, z. B. Rendering und Layout, durch ein Objekt.

Ausgabe von Visual Profiler

Visual Profiler-Anzeigeausgabe

Visuelles Renderingverhalten

WPF führt eine Reihe von Features ein, die das Renderingverhalten visueller Objekte beeinflussen: Grafiken mit Speichermodus, Vektorgrafiken und geräteunabhängige Grafiken.

Grafiken mit Speichermodus

Einer der Schlüssel zum Verstehen der Rolle von visuellen Objekten besteht darin, den Unterschied zwischen Grafiksystemen mit unmittelbarem Modus und Grafiksystemen mit Speichermodus zu verstehen. Eine Win32-Standardanwendung, die auf GDI oder GDI+ basiert, verwendet ein Grafiksystem mit unmittelbarem Modus. Das heißt, die Anwendung ist dafür verantwortlich, den Teil des Clientbereichs neu zu zeichnen, der durch eine Aktion wie die Änderung der Größe eines Fensters oder der visuellen Darstellung eines Objekts ungültig gemacht wird.

Diagramm der Win32-Renderingsequenz

Diagramm der Win32-Renderingsequenz

Im Gegensatz dazu verwendet WPF ein System mit Speichermodus. Das heißt, dass Anwendungsobjekte mit einer visuellen Darstellung einen Satz serialisierter Zeichnungsdaten definieren. Nachdem die Zeichnungsdaten definiert wurden, ist das System bei allen Neuzeichnungsanforderungen für das Rendering der Anwendungsobjekte verantwortlich. Selbst zur Laufzeit können Sie Anwendungsobjekte ändern oder erstellen und sich trotzdem darauf verlassen, dass das System auf Zeichnungsanforderungen reagiert. Die Leistung eines Grafiksystems mit Speichermodus besteht darin, dass die Zeichnungsinformationen von der Anwendung immer in einem serialisierten Zustand beibehalten werden, die Verantwortung für das Rendering aber beim System verbleibt. Das folgende Diagramm zeigt, wie sich die Anwendung für die Reaktion auf Zeichnungsanforderungen auf WPF verlässt.

Diagramm der WPF-Renderingsequenz

Diagramm der WPF-Renderingsequenz

Intelligentes Neuzeichnen

Einer der größten Vorteile bei der Verwendung von Grafiken mit Speichermodus besteht darin, dass WPF das, was in der Anwendung neu gezeichnet werden muss, effizient optimieren kann. Auch bei einer komplexen Szene mit verschiedenen Durchlässigkeitsgraden müssen Sie im Allgemeinen keinen Code für besondere Zwecke schreiben, um das Neuzeichnen zu optimieren. Vergleichen Sie dies mit der Win32-Programmierung, bei der Sie möglicherweise zur Optimierung Ihrer Anwendung mit großem Aufwand das Neuzeichnen im Aktualisierungsbereich auf ein Minimum zurückführen müssen. Unter Neuzeichnen im Aktualisierungsbereich finden Sie ein Beispiel dafür, wie komplex das Optimieren des Neuzeichnens in Win32-Anwendungen sein kann.

Vektorgrafiken

WPF verwendet Vektorgrafiken als Renderingdatenformat. Vektorgrafiken – dazu gehören skalierbare Vektorgrafiken (SVG), Windows-Metadateien (WMF) und TrueType-Schriftarten – speichern Renderingdaten und übertragen sie als Liste mit Anweisungen, die beschreiben, wie ein Bild mit Grafikprimitiven neu erstellt wird. Bei TrueType-Schriftarten handelt es sich z. B. um Outlineschriftarten, die statt eines Pixelarrays einen Satz von Linien, Kurven und Befehlen beschreiben. Einer der zentralen Vorteile von Vektorgrafiken ist die Möglichkeit, sie auf eine beliebige Größe und Auflösung zu skalieren.

Im Gegensatz zu Vektorgrafiken speichern Bitmapgrafiken Renderingdaten als pixelweise, vorab für eine bestimmte Auflösung gerenderte Darstellung eines Bilds. Einer der wichtigsten Unterschiede zwischen Bitmap- und Vektorgrafikformaten ist die Wiedergabetreue im Verhältnis zum ursprünglichen Quellbild. Wenn z. B. die Größe eines Quellbilds geändert wird, strecken Bitmapgrafiksysteme das Bild, während Vektorgrafiksysteme das Bild skalieren und so die Wiedergabetreue für das Bild erhalten.

Die folgende Abbildung zeigt ein Quellbild, das um 300 % vergrößert wurde. Beachten Sie die Verzerrungen, die entstehen, wenn das Quellbild als Bitmapgrafik gestreckt und nicht als Vektorgrafikbild skaliert wird.

Unterschiede zwischen Raster- und Vektorgrafiken

Unterschiede zwischen Raster- und Vektorgrafiken

Das folgende Markup zeigt zwei definierte Path-Elemente. Das zweite Elemente ändert mit ScaleTransform die Größe in den Zeichnungsanweisungen des ersten Elements um 300 %. Beachten Sie, dass die Zeichnungsanweisungen in den Path-Elementen unverändert bleiben.

<Path
  Data="M10,100 C 60,0 100,200 150,100 z"
  Fill="{StaticResource linearGradientBackground}"
  Stroke="Black"
  StrokeThickness="2" />

<Path
  Data="M10,100 C 60,0 100,200 150,100 z"
  Fill="{StaticResource linearGradientBackground}"
  Stroke="Black"
  StrokeThickness="2" >
  <Path.RenderTransform>
    <ScaleTransform ScaleX="3.0" ScaleY="3.0" />
  </Path.RenderTransform>
</Path>

Informationen über Auflösung und geräteunabhängige Grafiken

Es gibt zwei Systemfaktoren, die die Größe von Text und Grafiken auf dem Bildschirm bestimmen: Auflösung und DPI. Mit Auflösung wird die Anzahl der auf dem Bildschirm angezeigten Pixel beschrieben. Mit höherer Auflösung werden Pixel kleiner und lassen Grafiken und Text kleiner erscheinen. Eine Grafik, die auf einem Monitor mit 1024 x 768 angezeigt wird, erscheint viel kleiner, wenn die Auflösung in 1600 x 1200 geändert wird.

Die andere Systemeinstellung, DPI, beschreibt die Größe eines Bildschirmzolls in Pixeln. Die meisten Windows-Systeme besitzen 96 DPI, d. h., ein Bildschirmzoll enthält 96 Pixel. Durch Erhöhen der DPI-Einstellung wird der Bildschirmzoll größer, durch Verringern kleiner. Das heißt, die Größe eines Bildschirmzolls entspricht nicht der eines Zolls in der realen Welt (das trifft wahrscheinlich auf die meisten Systeme zu). Wenn Sie die DPI-Einstellung erhöhen, werden Grafiken und Text, die diesen Wert berücksichtigen, größer, da Sie den Bildschirmzoll vergrößert haben. Die Erhöhung der DPI-Einstellung kann insbesondere bei hohen Auflösungen die Lesbarkeit des Textes verbessern.

Nicht alle Anwendungen berücksichtigen die DPI-Einstellung: Einige verwenden Hardwarepixel als primäre Maßeinheit, und die Änderung der DPI-Einstellung des Systems hat auf diese Anwendungen keine Auswirkungen. Viele andere Anwendungen verwenden Einheiten, die die DPI-Einstellung berücksichtigen, zur Beschreibung von Schriftgraden, aber Pixel zur Beschreibung von allem anderen. Eine zu niedrige oder zu hohe DPI-Einstellung kann bei diesen Anwendungen zu Layoutproblemen führen, da der Text der Anwendung mit der DPI-Einstellung des Systems skaliert wird, die Benutzeroberfläche der Anwendung hingegen nicht. Dieses Problem tritt nicht mehr bei Anwendungen auf, die mit WPF entwickelt wurden.

WPF unterstützt die automatische Skalierung, indem statt Hardwarepixel geräteunabhängige Pixel als primäre Maßeinheit verwendet werden. Grafiken und Text werden ohne zusätzliche Bearbeitung durch die Anwendungsentwickler ordnungsgemäß skaliert. Die folgende Abbildung zeigt ein Beispiel dafür, wie WPF-Text und -Grafiken bei unterschiedlichen DPI-Einstellungen angezeigt werden.

Grafiken und Text bei verschiedenen DPI-Einstellungen

Grafiken und Text mit unterschiedlichen DPI-Einstellungen

VisualTreeHelper-Klasse

Die VisualTreeHelper-Klasse ist eine statische Hilfsklasse, die Low-Level-Funktionen für die Programmierung auf der Ebene der visuellen Objekte bereitstellt. Das ist in sehr spezifischen Szenarien hilfreich, z. B. bei der Entwicklung von benutzerdefinierten Steuerelementen mit hoher Leistung. In den meisten Fällen bieten die WPF-Frameworkobjekte auf höherer Ebene, z. B. Canvas und TextBlock, größere Flexibilität und Bedienungsfreundlichkeit.

Treffertests

Die VisualTreeHelper-Klasse bietet Methoden für Treffertests für visuelle Objekte, wenn die standardmäßige Unterstützung für Treffertests nicht Ihren Anforderungen entspricht. Sie können mit den HitTest-Methoden in der VisualTreeHelper-Klasse bestimmen, ob eine Geometrie oder ein Punktkoordinatenwert sich innerhalb der Begrenzung eines bestimmten Objekts, z. B. eines Steuerelements oder eines grafischen Elements, befindet. Sie könnten z. B. mit Treffertests bestimmen, ob ein Mausklick innerhalb des umgebenden Rechtecks eines Objekts in die Geometrie eines Kreises fällt. Sie haben auch die Möglichkeit, die Standardimplementierung der Treffertests zu überschreiben, um eigene benutzerdefinierte Treffertestberechnungen durchzuführen.

Weitere Informationen zu Treffertests finden Sie unter Treffertests in der visuellen Ebene.

Auflisten der visuellen Struktur

Die VisualTreeHelper-Klasse stellt Funktionalität zum Auflisten der Member einer visuellen Struktur bereit. Zum Abrufen eines übergeordneten Elements rufen Sie die GetParent-Methode auf. Um ein untergeordnetes Element oder ein in der Hierarchie unmittelbares Nachfolgerelement eines visuellen Objekts abzurufen, rufen Sie die GetChild-Methode auf. Diese Methode gibt ein untergeordnetes Visual des übergeordneten Elements am angegebenen Index zurück.

Im folgenden Beispiel wird gezeigt, wie alle Nachfolgerelemente eines visuellen Objekts aufgelistet werden. Dieses Verfahren können Sie verwenden, wenn Sie alle Renderinginformationen einer Hierarchie visueller Objekte serialisieren möchten.

        ' Enumerate all the descendants of the visual object.
        Public Shared Sub EnumVisual(ByVal myVisual As Visual)
            For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(myVisual) - 1
                ' Retrieve child visual at specified index value.
                Dim childVisual As Visual = CType(VisualTreeHelper.GetChild(myVisual, i), Visual)

                ' Do processing of the child visual object.

                ' Enumerate children of the child visual object.
                EnumVisual(childVisual)
            Next i
        End Sub
// Enumerate all the descendants of the visual object.
static public void EnumVisual(Visual myVisual)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
    {
        // Retrieve child visual at specified index value.
        Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);

        // Do processing of the child visual object.

        // Enumerate children of the child visual object.
        EnumVisual(childVisual);
    }
}

In den meisten Fällen ist die logische Struktur eine hilfreichere Darstellung der Elemente in einer WPF-Anwendung. Auch wenn Sie die logische Struktur nicht direkt ändern, ist diese Ansicht der Anwendung hilfreich, um Eigenschaftenvererbung und Ereignisrouting zu verstehen. Im Gegensatz zur visuellen Struktur kann die logische Struktur nicht visuelle Datenobjekte, z. B. ListItem, darstellen. Weitere Informationen über die logische Struktur finden Sie unter Strukturen in WPF.

Die VisualTreeHelper-Klasse stellt Methoden zum Zurückgeben des umgebenden Rechtecks visueller Objekte bereit. Sie können das umgebende Rechteck eines visuellen Objekts durch Aufrufen von GetContentBounds zurückgeben. Das umgebende Rechteck aller Nachfolgerelemente eines visuellen Objekts, einschließlich des visuellen Objekts selbst, können Sie durch Aufrufen von GetDescendantBounds zurückgeben. Im folgenden Code wird gezeigt, wie das umgebende Rechteck eines visuellen Objekts und all seiner Nachfolgerelemente in der Hierarchie berechnet wird.

            ' Return the bounding rectangle of the parent visual object and all of its descendants.
            Dim rectBounds As Rect = VisualTreeHelper.GetDescendantBounds(parentVisual)
// Return the bounding rectangle of the parent visual object and all of its descendants.
Rect rectBounds = VisualTreeHelper.GetDescendantBounds(parentVisual);

Siehe auch

Referenz

Visual

VisualTreeHelper

DrawingVisual

Konzepte

Optimieren der Leistung: 2D-Grafiken und Bildverarbeitung

Treffertests in der visuellen Ebene

Verwenden von DrawingVisual-Objekten

Lernprogramm: Hosten von visuellen Objekten in einer Win32-Anwendung

Optimieren der WPF-Anwendungsleistung