可以通过矩阵变换来给几何图形作平移(Translation)、旋转(Rotate)、扭曲(Skew)和大小变换(Scale):
View Code
#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(); }
在给带边框的几何图形作形变时,会导致边框也产生变化,如果这不是想要的情况,可以:
1、给几何图形单独定义边框
2、使用形变几何图形(ID2D1TransformedGeometry),来维护边框不变:
View Code
#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(); }
此外,还可以通过给画笔(ID2D1Brush)设置矩阵变换(Matrix3x2F)来显示不同的图形:
View Code
#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(); }