Windows Dev Center

Interoperabilität von DirectX und XAML (Windows-Runtime-Apps mit DirectX und C++)

Mit der Veröffentlichung von Windows 8 können Sie Extensible Application Markup Language (XAML) und Microsoft DirectX gemeinsam in Ihrer Windows Store-App verwenden. Dank der Kombination von XAML und DirectX können Sie flexible Frameworks für die Benutzeroberflächen erstellen, die mit den über DirectX gerenderten Inhalten kompatibel sind. Dies ist besonders für grafisch aufwendige Apps von Vorteil. In diesem Thema wird der Aufbau einer Windows Store-App erklärt, die mit DirectX arbeitet. Zudem gehen wir auf wichtige Typen ein, die beim Erstellen Ihrer Windows Store-App für die Zusammenarbeit mit DirectX erforderlich sind.

Hinweis  DirectX-APIs sind nicht als Windows-Runtime-Typen definiert. Daher verwenden Sie in der Regel Visual C++-Komponentenerweiterungen (C++/CX), um XAML-Windows Store-App-Komponenten zu entwickeln, die mit DirectX zusammenarbeiten. Sie können auch eine Windows Store-App mit C# und XAML erstellen, die DirectX verwendet, indem Sie die DirectX-Aufrufe in eine separate Windows-Runtime-Metadatendatei einschließen.

XAML und DirectX

DirectX bietet mit Direct2D und Microsoft Direct3D zwei leistungsstarke Bibliotheken für 2D- und 3D-Grafiken. Obwohl XAML grundlegende 2D-Grundtypen und -Effekte unterstützt, erfordern zahlreiche Apps, wie Modellierungs-Apps und Spiele, eine komplexere Grafikunterstützung. In diesen Fällen können Sie Grafiken teilweise oder vollständig mit Direct2D und Direct3D rendern und XAML für alles andere verwenden.

Für das Szenario mit gemeinsamer Verwendung von XAML und DirectX müssen Sie mit den folgenden beiden Begriffen vertraut sein:

  • Bei gemeinsam genutzten Flächen (Shared Surfaces) handelt es sich um Anzeigebereiche bestimmter Größe, die von XAML definiert werden. In diesen Bereichen können Sie mit DirectX und Windows::UI::Xaml::Media::Brush-Typen indirekt zeichnen. Bei gemeinsam genutzten Flächen steuern Sie keine Aufrufe zum Präsentieren der Swapchain(n). Änderungen an den gemeinsam genutzten Flächen werden mit den Updates des XAML-Frameworks synchronisiert.
  • Der zweite Begriff ist die Swapchain selbst. Sie liefert den Hintergrundpuffer für die DirectX-Rendering-Pipeline, also den Speicherbereich, der für die Anzeige präsentiert wird, nachdem das Renderziel fertiggestellt wurde.

Wägen Sie ab, wofür Sie DirectX verwenden. Wird es für die Zusammenstellung und Animierung eines einzelnen Steuerelements verwendet, das in die Abmessungen des Anzeigefensters passt? Kann die zusammengefasste Oberfläche von anderen Oberflächen oder dem Bildschirmrand ausgeblendet werden? Wird eine Ausgabe enthalten sein, die wie in einem Spiel in Echtzeit gerendert und gesteuert werden muss?

Sobald Sie festgelegt haben, wie DirectX verwendet werden soll, können Sie einen dieser Windows-Runtime-Typen verwenden, um DirectX-Rendering in eine Windows Store-App zu integrieren:

  • Wenn Sie ein statisches Bild erstellen oder ein komplexes Bild in ereignisgesteuerten Intervallen zeichnen möchten, zeichnen Sie mit der Klasse Windows::UI::Xaml::Media::Imaging::SurfaceImageSource in eine gemeinsam genutzte Fläche. Dieser Typ ermöglicht das Handle einer DirectX-Zeichenoberfläche von bestimmter Größe. In der Regel wird dieser Typ beim Erstellen eines Bilds oder einer Textur als Bitmap verwendet, um in einem Dokument oder als UI-Element angezeigt zu werden. Der Typ ist in Szenarien mit Echtzeitinteraktivität, wie ein hochleistungsfähiges Spiel, nicht so gut geeignet. Dies liegt daran, dass Updates des SurfaceImageSource-Objekts mit Updates der XAML-Benutzeroberfläche synchronisiert werden. Somit kann es zu Verzögerungen beim visuellen Feedback kommen. Dazu zählen eine schwankende Bildrate oder eine wahrnehmbare Antwortverzögerung auf Echtzeiteingaben. Die Updates sind aber immer noch schnell genug für dynamische Steuerelemente oder Datensimulationen.

    SurfaceImageSource-Grafikobjekte können mit anderen XAML-UI-Elementen zusammengefasst werden. Sie können sie umwandeln oder projizieren, wobei das XAML-Framework jegliche Deckkraft- oder Z-Index-Werte berücksichtigt.

  • Wenn das Bild größer ist als der verfügbare Platz auf dem Bildschirm und wenn es vom Benutzer geschwenkt und gezoomt werden kann, verwenden Sie die Klasse Windows::UI::Xaml::Media::Imaging::VirtualSurfaceImageSource. Dieser Typ ermöglicht das Handle einer DirectX-Zeichenoberfläche, die größer als der Bildschirm ist. Genau wie SurfaceImageSource wird diese Klasse für die Erstellung eines komplexen Bilds oder für ein dynamisches Steuerelement verwendet. Und genau wie SurfaceImageSource ist diese Klasse nicht so gut für hochleistungsfähige Spiele geeignet. Beispielhafte XAML-Elemente, welche die Klasse VirtualSurfaceImageSource verwenden können, sind Kartensteuerelemente oder ein Viewer für große Dokumente mit hoher Bilddichte.

  • Wenn Sie DirectX verwenden, um Grafiken zu präsentieren, die in Echtzeit aktualisiert werden oder die in regelmäßigen Intervallen mit niedriger Verzögerung aktualisiert werden müssen, verwenden Sie die SwapChainPanel-Klasse. So können Sie Grafiken aktualisieren, ohne dass eine Synchronisation mit dem Aktualisierungstimer des XAML-Frameworks erforderlich ist. Mit dieser Klasse können Sie direkt auf die Swapchain (IDXGISwapChain1) der Grafikhardware zugreifen und XAML oberhalb des Renderziels anordnen. Dieser Typ ist hervorragend für Spiele und andere DirectX-Apps mit Vollbildansicht geeignet, in denen eine XAML-basierte Benutzeroberfläche erforderlich ist. Wenn Sie diese Vorgehensweise wählen, sollten Sie sich mit DirectX sehr gut auskennen, z. B. in Bezug auf die Bereiche Microsoft DirectX Graphics Infrastructure (DXGI), Direct2D und Direct3D. Weitere Informationen finden Sie unter Programmieranleitung für Direct3D 11.

SurfaceImageSource

Die SurfaceImageSource-Klasse bietet gemeinsam genutzte Flächen, in die mit DirectX gezeichnet werden kann, und setzt die einzelnen Bestandteile dann zu App-Inhalten zusammen.

Im Folgenden erfahren Sie mehr über die grundlegende Vorgehensweise zum Erstellen und Aktualisieren eines SurfaceImageSource-Objekts im CodeBehind:

  1. Legen Sie die Größe der gemeinsam genutzten Fläche fest, indem Sie die Werte für die Höhe und Breite an den Konstruktor der Klasse SurfaceImageSource übergeben. Sie können ebenfalls festlegen, ob für die gemeinsam genutzte Fläche Alpha-Unterstützung (Deckkraft) erforderlich ist.

    Beispiel:

    SurfaceImageSource^ surfaceImageSource = ref new SurfaceImageSource(400, 300);

  2. Rufen Sie einen Zeiger zur Schnittstelle ISurfaceImageSourceNative ab. Wandeln Sie das SurfaceImageSource-Objekt in IInspectable (oder IUnknown) um, und rufen Sie QueryInterface dafür auf, um die zugrunde liegende ISurfaceImageSourceNative-Implementierung abzurufen. Die für diese Implementierung festgelegten Methoden verwenden Sie dann, um das entsprechende Gerät festzulegen und die Zeichenoperationen auszuführen.

    
    
    Microsoft::WRL::ComPtr<ISurfaceImageSourceNative>	m_sisNative;
    // ...
    IInspectable* sisInspectable = (IInspectable*) reinterpret_cast<IInspectable*>(surfaceImageSource);
    sisInspectable->QueryInterface(__uuidof(ISurfaceImageSourceNative), (void **)&m_sisNative);
    	
    
    
  3. Legen Sie das DXGI-Gerät fest, indem Sie die Methode D3D11CreateDevice aufrufen und dann das Gerät und den Inhalt an ISurfaceImageSourceNative::SetDevice übergeben. Beispiel:

    
    
    Microsoft::WRL::ComPtr<ID3D11Device>				m_d3dDevice;
    Microsoft::WRL::ComPtr<ID3D11DeviceContext>			m_d3dContext;
    // ...
    D3D11CreateDevice(
    		NULL,
    		D3D_DRIVER_TYPE_HARDWARE,
    		NULL,
    		flags,
    		featureLevels,
    		ARRAYSIZE(featureLevels),
    		D3D11_SDK_VERSION,
    		&m_d3dDevice,
    		NULL,
    		&m_d3dContext
    		)
    	);	
    Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice;
    m_d3dDevice.As(&dxgiDevice);
    // ...
    m_sisNative->SetDevice(dxgiDevice.Get());
    
    
  4. Stellen Sie einen Zeiger für das IDXGISurface-Objekt zur Methode ISurfaceImageSourceNative::BeginDraw bereit, und zeichnen Sie mit DirectX in dieser Fläche. Es wird nur in dem Bereich gezeichnet, der im Parameter updateRect für Updates festgelegt wurde.

    Hinweis  Sie können nur einen verbleibenden aktiven BeginDraw-Vorgang auf einmal pro IDXGIDevice haben.

    Die Methode gibt den X-Y-Punkt-Offset für das Zielrechteck als Parameter offset zurück. Anhand dieser Information bestimmen Sie, wo Sie innerhalb der Schnittstelle IDXGISurface zeichnen.

    
    ComPtr<IDXGISurface> surface;
    
    HRESULT beginDrawHR = m_sisNative->BeginDraw(updateRect, &surface, &offset);
    if (beginDrawHR == DXGI_ERROR_DEVICE_REMOVED || beginDrawHR == DXGI_ERROR_DEVICE_RESET)
    {
    		  // device changed
    }
    else
    {
        // draw to IDXGISurface (the surface paramater)
    }
    
    
    
  5. Rufen Sie die ISurfaceImageSourceNative::EndDraw-Methode auf, um die Bitmap fertigzustellen. Übergeben Sie die Bitmap an eine ImageBrush-Klasse.

    
    m_sisNative->EndDraw();
    // ...
    // The SurfaceImageSource object's underlying ISurfaceImageSourceNative object contains the completed bitmap.
    ImageBrush^ brush = ref new ImageBrush();
    brush->ImageSource = surfaceImageSource;
    
    
    
  6. Verwenden Sie die ImageBrush-Klasse, um die Bitmap zu zeichnen.

Hinweis  Das Aufrufen von SurfaceImageSource::SetSource (von IBitmapSource::SetSource geerbt) löst momentan eine Ausnahme aus. Rufen Sie es nicht von Ihrem SurfaceImageSource-Objekt auf.

VirtualSurfaceImageSource

Die Klasse VirtualSurfaceImageSource wird von der Klasse SurfaceImageSource erweitert, wenn die Inhalte potenziell zu groß sind, um auf dem Bildschirm angezeigt zu werden. Daher müssen die Inhalte für ein optimales Rendering virtualisiert werden.

VirtualSurfaceImageSource unterscheidet sich insofern von SurfaceImageSource, als es mit der Callback-Methode IVirtualSurfaceImageSourceCallbacksNative::UpdatesNeeded arbeitet. Die Callback-Methode wird implementiert, um bestimmte Bereiche der Fläche zu aktualisieren, sobald sie auf dem Bildschirm angezeigt werden. Somit müssen Sie keine ausgeblendeten Bereiche löschen, da das XAML-Framework diese Aufgabe für Sie übernimmt.

Im Folgenden erfahren Sie mehr über die grundlegende Vorgehensweise zum Erstellen und Aktualisieren eines VirtualSurfaceImageSource-Objekts im CodeBehind:

  1. Erstellen Sie eine Instanz der Klasse VirtualSurfaceImageSource in der gewünschten Größe. Beispiel:

    VirtualSurfaceImageSource^ virtualSIS = ref new VirtualSurfaceImageSource(2000, 2000);

  2. Rufen Sie einen Zeiger zur Schnittstelle IVirtualSurfaceImageSourceNative ab. Wandeln Sie das VirtualSurfaceImageSource-Objekt in IInspectable oder IUnknown um, und rufen Sie QueryInterface dafür auf, um die zugrunde liegende IVirtualSurfaceImageSourceNative-Implementierung abzurufen. Die für diese Implementierung festgelegten Methoden verwenden Sie dann, um das entsprechende Gerät festzulegen und die Zeichenoperationen auszuführen.

    
    
    Microsoft::WRL::ComPtr<IVirtualSurfaceImageSourceNative>	m_vsisNative;
    // ...
    IInspectable* vsisInspectable = (IInspectable*) reinterpret_cast<IInspectable*>(virtualSIS);
    vsisInspectable->QueryInterface(__uuidof(IVirtualSurfaceImageSourceNative), (void **)&m_vsisNative);
    	
    
    
  3. Legen Sie das DXGI-Gerät fest, indem Sie die Methode IVirtualSurfaceImageSourceNative::SetDevice aufrufen. Beispiel:

    
    
    Microsoft::WRL::ComPtr<ID3D11Device>				m_d3dDevice;
    Microsoft::WRL::ComPtr<ID3D11DeviceContext>			m_d3dContext;
    // ...
    D3D11CreateDevice(
    		NULL,
    		D3D_DRIVER_TYPE_HARDWARE,
    		NULL,
    		flags,
    		featureLevels,
    		ARRAYSIZE(featureLevels),
    		D3D11_SDK_VERSION,
    		&m_d3dDevice,
    		NULL,
    		&m_d3dContext
    		)
    	);	
    Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice;
    m_d3dDevice.As(&dxgiDevice);
    // ...
    m_vsisNative->SetDevice(dxgiDevice.Get());
    
    
  4. Rufen Sie die Methode IVirtualSurfaceImageSourceNative::RegisterForUpdatesNeeded auf, wodurch eine Referenz zu Ihrer Implementierung der Schnittstelle IVirtualSurfaceUpdatesCallbackNative übergeben wird.

    
    
    class MyContentImageSource : public IVirtualSurfaceUpdatesCallbackNative
    {
    // ...
      private:
         virtual HRESULT STDMETHODCALLTYPE UpdatesNeeded() override;
    }
    
    // ...
    
    HRESULT STDMETHODCALLTYPE MyContentImageSource::UpdatesNeeded()
    {
      // .. perform drawing here ...
    }
    void MyContentImageSource::Initialize()
    {
      // ...
      m_vsisNative->RegisterForUpdatesNeeded(this);
      // ...
    }
    
    
    

    Daraufhin ruft das Framework Ihre Implementierung der Methode IVirtualSurfaceUpdatesCallbackNative::UpdatesNeeded auf, wenn ein Bereich der Klasse VirtualSurfaceImageSource aktualisiert werden muss.

    Dies ist dann der Fall, wenn das Framework den Bereich erkennt, der gezeichnet werden muss (wenn der Benutzer die Ansicht der Fläche schwenkt oder zoomt), oder wenn die App die Methode IVirtualSurfaceImageSourceNative::Invalidate in diesem Bereich aufgerufen hat.

  5. Innerhalb der Methode IVirtualSurfaceImageSourceNative::UpdatesNeeded verwenden Sie die Methoden IVirtualSurfaceImageSourceNative::GetUpdateRectCount und IVirtualSurfaceImageSourceNative::GetUpdateRects, um zu bestimmen, welche(r) Bereich(e) der Fläche gezeichnet werden muss/müssen.

    
    
    
    
    HRESULT STDMETHODCALLTYPE MyContentImageSource::UpdatesNeeded()
    {
        HRESULT hr = S_OK;
    
        try
        {
            ULONG drawingBoundsCount = 0;  
    
    		      m_vsisNative->GetUpdateRectCount(&drawingBoundsCount);
            std::unique_ptr<RECT[]> drawingBounds(new RECT[drawingBoundsCount]);
            m_vsisNative->GetUpdateRects(drawingBounds.get(), drawingBoundsCount);
            
            for (ULONG i = 0; i < drawingBoundsCount; ++i)
            {
                // Drawing code here ...
            }
        }
        catch (Platform::Exception^ exception)
        {
            hr = exception->HResult;
        }
    
        return hr;
    }
    
    
  6. Führen Sie schließlich Folgendes für jeden Bereich aus, der aktualisiert werden soll:

    1. Stellen Sie einen Zeiger für das IDXGISurface-Objekt zur Methode IVirtualSurfaceImageSourceNative::BeginDraw bereit, und zeichnen Sie mit DirectX in dieser Fläche. Es wird nur in dem Bereich gezeichnet, der im Parameter updateRect für Updates festgelegt wurde.

      Wie bei IlSurfaceImageSourceNative::BeginDraw gibt diese Methode den X-Y-Punkt-Offset für das aktualisierte Zielrechteck als Parameter offset zurück. Anhand dieser Information bestimmen Sie, wo Sie innerhalb der Schnittstelle IDXGISurface zeichnen.

      Hinweis  Sie können nur einen verbleibenden aktiven BeginDraw-Vorgang auf einmal pro IDXGIDevice haben.
      
      ComPtr<IDXGISurface> bigSurface;
      
      HRESULT beginDrawHR = m_vsisNative->BeginDraw(updateRect, &bigSurface, &offset);
      if (beginDrawHR == DXGI_ERROR_DEVICE_REMOVED || beginDrawHR == DXGI_ERROR_DEVICE_RESET)
      {
      		  // device changed
      }
      else
      {
          // draw to IDXGISurface
      }
      
      
      
    2. Zeichnen Sie Ihre spezifischen Inhalte in diesem Bereich. Achten Sie aber darauf, dass Sie das Zeichnen auf die begrenzten Bereiche beschränken, um die optimale Leistung sicherzustellen.

    3. Rufen Sie IVirtualSurfaceImageSourceNative::EndDraw. Als Ergebnis erhalten Sie eine Bitmap.

SwapChainPanel und Gaming

Die SwapChainPanel-Klasse ist ein Windows-Runtime-Typ, der für hochleistungsfähige Grafik und Spiele entwickelt wurde. Bei dieser Klasse wird die Swapchain direkt verwaltet. Sie erstellen in diesem Fall Ihre eigene DirectX-Swapchain und verwalten die Präsentation Ihrer gerenderten Inhalte selbst. Sie können dem SwapChainPanel-Objekt XAML-Elemente hinzufügen, wie Menüs, Head-up-Displays und sonstige UI-Überblendungen.

Es gibt gewisse Einschränkungen für die Klasse SwapChainPanel, um die bestmögliche Leistungsfähigkeit sicherzustellen:

  • Es sind nicht mehr als vier SwapChainPanel-Instanzen pro App vorhanden.
  • Die von der SwapChainPanel-Klasse geerbten Eigenschaften Opacity, RenderTransform, Projection und Clip werden nicht unterstützt.
  • Sie sollten die Höhe und Breite der DirectX-Swapchain (in der Struktur DXGI_SWAP_CHAIN_DESC1) entsprechend den aktuellen Abmessungen des App-Fensters festlegen. Wenn Sie dies nicht vornehmen, werden die Inhalte mit der Enumeration DXGI_SCALING_STRETCH passend skaliert.
  • Sie müssen den Skalierungsmodus der DirectX-Swapchain (in der Struktur DXGI_SWAP_CHAIN_DESC1) auf DXGI_SCALING_STRETCH setzen.
  • Sie können den Alpha-Modus der DirectX-Swapchain (in der Struktur DXGI_SWAP_CHAIN_DESC1) in DXGI_ALPHA_MODE_PREMULTIPLIED ändern.
  • Sie müssen die DirectX-Swapchain erstellen, indem Sie die Methode IDXGIFactory2::CreateSwapChainForComposition aufrufen.

Die Klasse SwapChainPanel wird basierend auf den Anforderungen Ihrer App aktualisiert und nicht entsprechend den Updates des XAML-Frameworks. Wenn Sie die Updates der Klasse SwapChainPanel mit denen des XAML-Frameworks synchronisieren möchten, registrieren Sie die Klasse für das Ereignis Windows::UI::Xaml::Media::CompositionTarget::Rendering. Andernfalls müssen Sie jegliche Thread-übergreifenden Probleme berücksichtigen, wenn Sie versuchen, die XAML-Elemente von einem anderen Thread aus zu aktualisieren als dem, der die Klasse SwapChainPanel aktualisiert.

Es gibt auch eine Reihe von bewährten Methoden für die Verwendung der Klasse SwapChainPanel bei der App-Entwicklung.

  • Die Klasse SwapChainPanel erbt von der Klasse Windows::UI::Xaml::Controls::Grid und unterstützt ein ähnliches Layoutverhalten. Machen Sie sich mit dem Grid-Typ und seinen Eigenschaften vertraut.

  • Nachdem eine DirectX-Swapchain festgelegt wurde, arbeiten alle Eingabeereignisse, die für die Klasse SwapChainPanel ausgelöst wurden, auf die gleiche Weise wie bei allen anderen XAML-Elementen. Für die Klasse SwapChainPanel wird kein Hintergrundpinsel festgelegt, und Sie benötigen keine Eingabeereignisse von der CoreWindow-Klasse der App direkt zu verarbeiten, wie es in DirectX-Apps der Fall ist, die nicht mit der Klasse SwapChainPanel arbeiten.

  • Der gesamte Inhalt der visuellen XAML-Elementstruktur unter einem direkt einer Klasse SwapChainPanel untergeordneten Element wird entsprechend der Layoutgröße des unmittelbar untergeordneten Elements des SwapChainPanel-Objekts abgeschnitten. Jegliche Inhalte, die außerhalb dieser Layoutgrenzen transformiert werden, werden nicht gerendert. Platzieren Sie daher alle animierten XAML-Inhalte, die Sie mit einem XAML-Storyboard animieren, in der visuellen Struktur unterhalb eines Elements, dessen Layoutgrenzen groß genug für die vollständige Darstellung der Animation sind.

  • Verwenden Sie eine begrenzte Anzahl von visuellen XAML-Elementen, die einer SwapChainPanel-Klasse unmittelbar untergeordnet sind. Wenn möglich, gruppieren Sie dicht nebeneinander liegende Elemente unter einem gemeinsamen übergeordneten Element. Allerdings gibt es leistungsbezogene Abhängigkeiten zwischen der Anzahl an unmittelbar untergeordneten visuellen Elementen und der Größe der untergeordneten Elemente: Zu viele oder unnötig große XAML-Elemente können die Gesamtleistungsfähigkeit beeinträchtigen. Erstellen Sie außerdem keine einzelnen, untergeordneten Vollbild-XAML-Elemente für die Klasse SwapChainPanel Ihrer App, da dies zu Überzeichnungen in der App und zu verringerter Leistungsfähigkeit führt. Erstellen Sie generell nicht mehr als acht unmittelbar untergeordnete visuelle XAML-Elemente für die Klasse SwapChainPanel Ihrer App. Dabei darf das Layout jedes Elements nur so groß gewählt werden, wie es für die Darstellung der visuellen Inhalte erforderlich ist. Dennoch können Sie die visuelle Elementstruktur unter einem untergeordneten Element der Klasse SwapChainPanel ausreichend komplex gestalten, ohne dabei allzu große Leistungseinbußen hinnehmen zu müssen.

Hinweis   Im Allgemeinen sollten Ihre DirectX-Apps Swapchains im Querformat und entsprechend der angezeigten Fenstergröße erstellen (in den meisten Windows Store-Spielen für gewöhnlich die systemeigene Bildschirmauflösung). Dadurch wird sichergestellt, dass Ihre App die optimale Swapchainimplementierung verwendet, wenn sie über keine sichtbaren XAML-Overlays verfügt. Wenn sich die App in das Hochformat dreht, sollte IDXGISwapChain1::SetRotation in der vorhandenen Swapchain aufgerufen, falls erforderlich eine Umwandlung des Inhalts angewendet und anschließend SetSwapChain erneut auf der gleichen Swapchain aufgerufen werden. Ebenso sollte Ihre App bei jeder Größenänderung der Swapchain SetSwapChain durch einen Aufruf von IDXGISwapChain::ResizeBuffers erneut für dieselbe Swapchain aufrufen.

Im Folgenden erfahren Sie mehr über die grundlegende Vorgehensweise zum Erstellen und Aktualisieren eines SwapChainPanel-Objekts im CodeBehind:

  1. Rufen eine Instanz eines Swapchainbereichs für Ihre App ab. Die Instanzen werden in XAML mit dem Tag <SwapChainPanel> gekennzeichnet.

    Windows::UI::Xaml::Controls::SwapChainPanel^ swapChainPanel;

    Unten finden Sie ein Beispiel für das Tag <SwapChainPanel>.

    
    <SwapChainPanel x:Name="swapChainPanel">
        <SwapChainPanel.ColumnDefinitions>
            <ColumnDefinition Width="300*"/>
            <ColumnDefinition Width="1069*"/>
        </SwapChainPanel.ColumnDefinitions></SwapChainPanel>
    
    
    
  2. Rufen Sie einen Zeiger zur Schnittstelle ISwapChainPanelNative ab. Wandeln Sie das SwapChainPanel-Objekt in IInspectable (oder IUnknown) um, und rufen Sie QueryInterface dafür auf, um die zugrunde liegende ISwapChainPanelNative-Implementierung abzurufen.

    
    
    Microsoft::WRL::ComPtr<ISwapChainPanelNative>	m_swapChainNative;
    // ...
    IInspectable* panelInspectable = (IInspectable*) reinterpret_cast<IInspectable*>(swapChainPanel);
    panelInspectable->QueryInterface(__uuidof(ISwapChainPanelNative), (void **)&m_swapChainNative);
    	
    
    
  3. Erstellen Sie das DXGI-Gerät und die Swapchain, und legen Sie für die Swapchain die Schnittstelle ISwapChainPanelNative fest, indem Sie sie an die SetSwapChain-Methode übergeben.

    
    
    Microsoft::WRL::ComPtr<IDXGISwapChain1>				m_swapChain;	
    // ...
    DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
            swapChainDesc.Width = m_bounds.Width;
            swapChainDesc.Height = m_bounds.Height;
            swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;           // this is the most common swapchain format
            swapChainDesc.Stereo = false; 
            swapChainDesc.SampleDesc.Count = 1;                          // don't use multi-sampling
            swapChainDesc.SampleDesc.Quality = 0;
            swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
            swapChainDesc.BufferCount = 2;
            swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
            swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // we recommend using this swap effect for all applications
            swapChainDesc.Flags = 0;
            		
    // QI for DXGI device
    Microsoft::WRL::ComPtr<IDXGIDevice> dxgiDevice;
    m_d3dDevice.As(&dxgiDevice);
    
    // get the DXGI adapter
    Microsoft::WRL::ComPtr<IDXGIAdapter> dxgiAdapter;
    dxgiDevice->GetAdapter(&dxgiAdapter);
    
    // get the DXGI factory
    Microsoft::WRL::ComPtr<IDXGIFactory2> dxgiFactory;
    dxgiAdapter->GetParent(__uuidof(IDXGIFactory2), &dxgiFactory);
    // create swap chain by calling CreateSwapChainForComposition
    dxgiFactory->CreateSwapChainForComposition(
                m_d3dDevice.Get(),
                &swapChainDesc,
                nullptr,		// allow on any display 
                &m_swapChain
                );
    		
    m_swapChainNative->SetSwapChain(m_swapChain.Get());
    
    
  4. Zeichnen Sie in die DirectX-Swapchain, und präsentieren Sie sie, um die Inhalte anzuzeigen.

    
    HRESULT hr = m_swapChain->Present(1, 0);
    
    

    Die XAML-Elemente werden aktualisiert, wenn das Windows-Runtime-Layout/Rendering-Logik ein Update signalisiert.

Verwandte Themen

SurfaceImageSource
VirtualSurfaceImageSource
SwapChainPanel
ISwapChainPanelNative
Programmieranleitung für Direct3D 11
SwapChainPanel-Beispiele
SwapChainPanel-Beispiel für DirectX/XAML-Interoperabilität
SurfaceImageSource-Beispiele
SurfaceImageSource-Beispiel für DirectX/XAML-Interoperabilität
VirtualSurfaceImageSource-Beispiele
Beispiel für eine Direct2D-Zeitschriften-App

 

 

Anzeigen:
© 2015 Microsoft