Freigeben über


Abrufen von Geometriedaten durch Erweitern von ID2D1SimplifiedGeometrySink

Während ein ID2D1Geometry-Objekt unveränderlich ist, müssen Sie die Geometriedaten in einem Pfadgeometrieobjekt bearbeiten. Direct2D ermöglicht Ihnen dies, indem Sie eine erweiterbare Schnittstelle namens ID2D1SimplifiedGeometrySink bereitstellen. In diesem Thema wird beschrieben, wie Sie diese Schnittstelle erweitern, um die Geometriedaten aus einem Pfadgeometrieobjekt abzurufen.

So erweitern Sie die ID2D1SimplifiedGeometrySink-Schnittstelle

  1. Implementieren Sie eine Klasse, die von ID2D1SimplifiedGeometrySink erbt.
  2. Erstellen Sie eine instance dieser Klasse, und übergeben Sie sie an ID2D1Geometry::Simplify.

Im folgenden Codebeispiel wird gezeigt, wie eine Klasse namens SpecializedSink implementiert wird, die von der ID2D1SimplifiedGeometrySink-Schnittstelle erbt . Der Einfachheit halber ruft die erweiterte AddLines-Methode die Geometriedaten ab und zeigt sie dann im Konsolenfenster an. Sie können diese Methode an Ihre spezifischen Datenanforderungen anpassen.

class SpecializedSink : public ID2D1SimplifiedGeometrySink
{
    public:
        SpecializedSink()
            : m_cRef(1)
        {
        }

        STDMETHOD_(ULONG, AddRef)(THIS)
        {
            return InterlockedIncrement(reinterpret_cast<LONG volatile *>(&m_cRef));
        }

        STDMETHOD_(ULONG, Release)(THIS)
        {
            ULONG cRef = static_cast<ULONG>(
            InterlockedDecrement(reinterpret_cast<LONG volatile *>(&m_cRef)));

            if(0 == cRef)
            {
                delete this;
            }

            return cRef;
        }

        STDMETHOD(QueryInterface)(THIS_ REFIID iid, void** ppvObject)
        {
            HRESULT hr = S_OK;

            if (__uuidof(IUnknown) == iid)
            {
                *ppvObject = static_cast<IUnknown*>(this);
                AddRef();
            }
            else if (__uuidof(ID2D1SimplifiedGeometrySink) == iid)
            {
                *ppvObject = static_cast<ID2D1SimplifiedGeometrySink*>(this);
                AddRef();
            }
            else
            {
                *ppvObject = NULL;
                hr = E_NOINTERFACE;
            }

            return hr;
        }

        STDMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT * /*beziers*/,
                                     UINT /*beziersCount*/)
        {
            // Customize this method to meet your specific data needs.
        }

        STDMETHOD_(void, AddLines)(const D2D1_POINT_2F *points, UINT pointsCount)
        {
            // Customize this method to meet your specific data needs.
            printf("\n\nRetrieving geometry data from a derived ID2D1SimplifiedGeometrySink object:\n");
            for (UINT i = 0; i < pointsCount; ++i)
            {
                printf("%.0f, %.0f\n", points[i].x, points[i].y);
            }
        }

        STDMETHOD_(void, BeginFigure)(D2D1_POINT_2F startPoint,
                                      D2D1_FIGURE_BEGIN figureBegin)
        {
        }

        STDMETHOD_(void, EndFigure)(D2D1_FIGURE_END figureEnd)
        {
        }

        STDMETHOD_(void, SetFillMode)(D2D1_FILL_MODE fillMode)
        {
        }

        STDMETHOD_(void, SetSegmentFlags)(D2D1_PATH_SEGMENT vertexFlags)
        {
        }

        STDMETHOD(Close)()
        {
            return S_OK;
        }

    private:
        UINT m_cRef;
};

Das Beispiel verwendet dann einen Satz von Daten (182, 209), (211, 251), (251, 226), (392, 360) und (101, 360), um eine aufgefüllte Pfadgeometrie (m_pGeometry) zu erstellen, in der Daten abgerufen werden können.

hr = m_pD2DFactory->CreatePathGeometry(&m_pGeometry);
if(SUCCEEDED(hr))
{
    ID2D1GeometrySink *pSink = NULL;

    hr = m_pGeometry->Open(&pSink);
    if (SUCCEEDED(hr))
    {
        pSink->SetFillMode(D2D1_FILL_MODE_WINDING);

        pSink->BeginFigure(
            D2D1::Point2F(101,360),
            D2D1_FIGURE_BEGIN_FILLED
            );
        D2D1_POINT_2F points[5] = {
           D2D1::Point2F(182,209),
           D2D1::Point2F(211,251),
           D2D1::Point2F(251,226),
           D2D1::Point2F(392,360),
           D2D1::Point2F(101,360),
           };

        printf("Adding the following geometry data to an ID2D1GeometrySink object:\n");
        printf("182, 209\n");
        printf("211, 251\n");
        printf("251, 226\n");
        printf("392, 360\n");
        printf("101, 360\n");

        pSink->AddLines(points, ARRAYSIZE(points));
        pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
        hr = pSink->Close();
        pSink->Release();

Schließlich erstellt das Beispiel ein SpecializedSink-Objekt und ruft dann die ID2D1Geometry::Simplify-Methode auf, wobei das SpecializedSink-Objekt und der parameter D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES übergeben werden, wodurch alle Kurven in Liniensegmente vereinfacht werden.

        SpecializedSink *pSpecializedSink = NULL;

        if (SUCCEEDED(hr))
        {
            pSpecializedSink = new SpecializedSink();
            if (!pSpecializedSink)
            {
                hr = E_OUTOFMEMORY;
            }
        }

        if (SUCCEEDED(hr))
        {
            hr = m_pGeometry->Simplify(
                    D2D1_GEOMETRY_SIMPLIFICATION_OPTION_LINES, // This causes any curves to be flattened into line segments.
                    NULL, // world transform
                    pSpecializedSink
                    );


            if (SUCCEEDED(hr))
            {
                hr = pSpecializedSink->Close();
            }

            pSpecializedSink->Release();
        }

Das Programm erstellt Ausgaben, wie im folgenden Screenshot gezeigt.

Screenshot eines Konsolenfensters mit Ausgabe zum Hinzufügen und Abrufen von Geometriedaten

Direct2D-Referenz