可以通过矩阵变换来给几何图形作平移(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();
}
在给带边框的几何图形作形变时,会导致边框也产生变化,如果这不是想要的情况,可以:
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();
}
此外,还可以通过给画笔(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();
}