Direct2D 变换

可以通过矩阵变换来给几何图形作平移(Translation)、旋转(Rotate)、扭曲(Skew)和大小变换(Scale):

#include "stdafx.h"

struct SampleWindow
    : DesktopWindow
{
    ComPtr m_geometry;
    ComPtr m_brush;

    void CreateDeviceIndependentResources()
    {
        HR(m_factory->CreateRectangleGeometry(
            RectF(0.0f, 0.0f, 200.0f, 100.0f), m_geometry.GetAddressOf()));
    }
    
    void CreateDeviceResources()
    {
        HR(m_target->CreateSolidColorBrush(
            COLOR_WHITE, m_brush.GetAddressOf()));
    }

    void DrawGeometry(const Matrix3x2F& matrix, const D2D1_COLOR_F& color)
    {
        m_brush->SetColor(color);
        m_target->SetTransform(matrix);
        m_target->FillGeometry(m_geometry.Get(), m_brush.Get());
    }

    void Draw()
    {
        m_target->Clear(COLOR_BLUE);

        m_brush->SetOpacity(0.75f);

        // 如果不用Identity,重绘的时候就会消失
        auto t = Matrix3x2F::Identity();
        DrawGeometry(t, COLOR_WHITE);

        t = Matrix3x2F::Translation(100.0f, 50.0f) * t;
        DrawGeometry(t, COLOR_YELLOW);

        t = Matrix3x2F::Scale(1.0f, 2.0f) * Matrix3x2F::Translation(100.0f, 50.0f) * t;
        DrawGeometry(t, COLOR_RED);

        t = Matrix3x2F::Skew(-45.0f, 0.0f) * Matrix3x2F::Translation(300.0f, 150.0f);
        DrawGeometry(t, COLOR_BLACK);

        t = Matrix3x2F::Rotation(45.0f) * Matrix3x2F::Translation(300.0f, 150.0f);
        DrawGeometry(t, COLOR_WHITE);
    }
};

int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    ComInitialize com;
    SampleWindow window;
    return window.Run();
}

Direct2D 变换_第1张图片

在给带边框的几何图形作形变时,会导致边框也产生变化,如果这不是想要的情况,可以:
1、给几何图形单独定义边框
2、使用形变几何图形(ID2D1TransformedGeometry),来维护边框不变:

#include "stdafx.h"

struct SampleWindow
    : DesktopWindow
{
    ComPtr m_geometry;
    ComPtr m_brush;
    ComPtr m_style;
    D2D1_POINT_2F m_offset;
    D2D1_POINT_2F m_anchor;

    void CreateDeviceIndependentResources()
    {
        auto rect = RectF(0.0f, 0.0f, 100.0f, 100.0f);

        ASSERT(!m_geometry);
        HR(m_factory->CreateRectangleGeometry(rect, m_geometry.GetAddressOf()));

        m_offset = Point2F(1.0f, 1.0f);
        m_anchor = Point2F();

        D2D1_STROKE_STYLE_PROPERTIES1 props = {};
        props.miterLimit = 10.0f;
        props.transformType = D2D1_STROKE_TRANSFORM_TYPE_FIXED;

        ASSERT(!m_style);
        HR(m_factory->CreateStrokeStyle(props, nullptr, 0, m_style.GetAddressOf()));
    }
    
    void CreateDeviceResources()
    {
        HR(m_target->CreateSolidColorBrush(
            COLOR_WHITE, m_brush.GetAddressOf()));
    }

    void Draw()
    {
        m_target->Clear(COLOR_BLUE);

        auto t = Matrix3x2F::Translation(50.0f, 50.0f);
        auto scale = Matrix3x2F::Scale(
            max(1.0f, m_offset.x), 
            max(1.0f, m_offset.y));

        m_target->SetTransform(scale * t);
        m_target->DrawGeometry(m_geometry.Get(), m_brush.Get(), 5.0f, m_style.Get());

        // 也可以使用以下方法来避免边缘发生形变
        /*ComPtr geometry;
        HR(m_factory->CreateTransformedGeometry(m_geometry.Get(), scale * t, geometry.GetAddressOf()));
        m_target->DrawGeometry(geometry.Get(), m_brush.Get(), 5.0f);*/
    }

    LRESULT MouseLeftButtonDownHandler(UINT, WPARAM, LPARAM lparam, BOOL&)
    {
        SetCapture();
        m_anchor.x = LOWORD(lparam);
        m_anchor.y = HIWORD(lparam);
        return 0;
    }

    LRESULT MouseLeftButtonUpHandler(UINT, WPARAM, LPARAM lparam, BOOL&)
    {
        ReleaseCapture();
        return 0;
    }

    LRESULT MouseMoveHandler(UINT, WPARAM wparam, LPARAM lparam, BOOL&)
    {
        auto x = (FLOAT)LOWORD(lparam);
        auto y = (FLOAT)HIWORD(lparam);

        if (wparam & MK_LBUTTON)
        {
            m_offset.x = 1 + (x - m_anchor.x) / 100.0f;
            m_offset.y = 1 + (y - m_anchor.y) / 100.0f;
            Invalidate();
        }
        return 0;
    }
};

int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    ComInitialize com;
    SampleWindow window;
    return window.Run();
}

Direct2D 变换_第2张图片Direct2D 变换_第3张图片

此外,还可以通过给画笔(ID2D1Brush)设置矩阵变换(Matrix3x2F)来显示不同的图形:

#include "stdafx.h"

struct SampleWindow
    : DesktopWindow
{
    ComPtr m_brush;

    void CreateDeviceIndependentResources()
    {
    }
    
    void CreateDeviceResources()
    {
        D2D1_GRADIENT_STOP stops[] = 
        {
            { 0.0f, COLOR_WHITE }, 
            { 1.0f, COLOR_BLUE }
        };

        ComPtr collection;
        HR(m_target->CreateGradientStopCollection(stops, _countof(stops), collection.GetAddressOf()));
        D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES props = {};
        HR(m_target->CreateLinearGradientBrush(props, collection.Get(), m_brush.GetAddressOf()));
    }

    void Draw()
    {
        auto size = m_target->GetSize();
        m_brush->SetEndPoint(Point2F(size.width, size.height));
        m_target->FillRectangle(RectF(0.0f, 0.0f, size.width, size.height), m_brush.Get());
    }

    LRESULT MouseMoveHandler(UINT, WPARAM, LPARAM lparam, BOOL&)
    {
        if (m_target)
        {
            auto size = m_target->GetSize();
            auto t = Matrix3x2F::Translation(LOWORD(lparam) - size.width, HIWORD(lparam) - size.height);
            m_brush->SetTransform(t);
            Invalidate();
        }
        return 0;
    }
};

int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
    ComInitialize com;
    SampleWindow window;
    return window.Run();
}

你可能感兴趣的:(Direct2D)