微软文档:Transforms
本篇通过官方文档学习,整理出来的demo,初始样本请先创建一个普通的desktop app。
ID2D1SolidColorBrush* m_pOriginalShapeBrush, * m_pFillBrush,* m_pTransformedShapeBrush; ID2D1StrokeStyle* m_pStrokeStyleDash; ... LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: { int wmId = LOWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } } break; case WM_PAINT: { Render(); ValidateRect(hWnd, NULL); } break; ... } ... void Render() { RECT rc; GetClientRect(hWnd, &rc); D2D1_SIZE_U size = D2D1::SizeU( rc.right - rc.left, rc.bottom - rc.top ); HRESULT hr = l->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(hWnd, size), &m_pRenderTarget ); m_pRenderTarget->BeginDraw(); m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White)); transform(); hr = m_pRenderTarget->EndDraw(); if (FAILED(hr) || hr == D2DERR_RECREATE_TARGET) { DiscardGraphicsResources(); } } void DiscardGraphicsResources() { SafeRelease(&m_pOriginalShapeBrush); SafeRelease(&m_pFillBrush); SafeRelease(&m_pTransformedShapeBrush); } void transform() { //旋转 HRESULT hr = m_pRenderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black, 1.0F), &m_pOriginalShapeBrush); if (SUCCEEDED(hr)) { hr = m_pRenderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF(0x9ACD32, 1.0f)), &m_pFillBrush ); } if (SUCCEEDED(hr)) { hr = m_pRenderTarget->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Blue, 1.0f), &m_pTransformedShapeBrush ); } // Dash array for dashStyle D2D1_DASH_STYLE_CUSTOM float dashes[] = { 1.0f, 2.0f, 2.0f, 3.0f, 2.0f, 2.0f }; // Stroke Style with Dash Style -- Custom if (SUCCEEDED(hr)) { hr = l->CreateStrokeStyle( D2D1::StrokeStyleProperties( D2D1_CAP_STYLE_FLAT, D2D1_CAP_STYLE_FLAT, D2D1_CAP_STYLE_ROUND, D2D1_LINE_JOIN_MITER, 10.0f, D2D1_DASH_STYLE_CUSTOM, 0.0f), dashes, ARRAYSIZE(dashes), &m_pStrokeStyleDash ); } // Create a rectangle. D2D1_RECT_F rectangle_1 = D2D1::Rect(438.0f, 301.5f, 498.0f, 361.5f); // Draw the rectangle. m_pRenderTarget->DrawRectangle( rectangle_1, m_pOriginalShapeBrush, 1.0f, m_pStrokeStyleDash ); // Apply the rotation transform to the render target. //m_pRenderTarget->SetTransform( // D2D1::Matrix3x2F::Rotation( // 45.0f, // D2D1::Point2F(468.0f, 331.5f)) //); //// Fill the rectangle. //m_pRenderTarget->FillRectangle(rectangle_1, m_pFillBrush); //// Draw the transformed rectangle. //m_pRenderTarget->DrawRectangle(rectangle_1, m_pTransformedShapeBrush); /*************************************************************************/ //缩放 // Create a rectangle. D2D1_RECT_F rectangle_2 = D2D1::Rect(438.0f, 80.5f, 498.0f, 140.5f); // Draw the outline of the rectangle. m_pRenderTarget->DrawRectangle( rectangle_2, m_pOriginalShapeBrush, 1.0f, m_pStrokeStyleDash ); //// Apply the scale transform to the render target. //m_pRenderTarget->SetTransform( // D2D1::Matrix3x2F::Scale( // D2D1::Size(1.3f, 1.3f), // D2D1::Point2F(438.0f, 80.5f)) //); //// Draw the outline of the rectangle. //m_pRenderTarget->DrawRectangle(rectangle_2, m_pTransformedShapeBrush); /*****************************************************************************/ //倾斜 // Create a rectangle. D2D1_RECT_F rectangle_3 = D2D1::Rect(126.0f, 301.5f, 186.0f, 361.5f); // Draw the outline of the rectangle. m_pRenderTarget->DrawRectangle( rectangle_3, m_pOriginalShapeBrush, 1.0f, m_pStrokeStyleDash ); //// Apply the skew transform to the render target. //m_pRenderTarget->SetTransform( // D2D1::Matrix3x2F::Skew( // 45.0f, // 10.0f, // D2D1::Point2F(126.0f, 301.5f)) //); //// Paint the interior of the rectangle. //m_pRenderTarget->FillRectangle(rectangle_3, m_pFillBrush); //// Draw the outline of the rectangle. //m_pRenderTarget->DrawRectangle(rectangle_3, m_pTransformedShapeBrush); /***************************************************************************/ //平移 // Create a rectangle. D2D1_RECT_F rectangle_4 = D2D1::Rect(126.0f, 80.5f, 186.0f, 140.5f); // Draw the outline of the rectangle. m_pRenderTarget->DrawRectangle( rectangle_4, m_pOriginalShapeBrush, 1.0f, m_pStrokeStyleDash ); // Apply the translation transform to the render target. m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Translation(20, 10)); // Paint the interior of the rectangle. m_pRenderTarget->FillRectangle(rectangle_4, m_pFillBrush); // Draw the outline of the rectangle. m_pRenderTarget->DrawRectangle(rectangle_4, m_pTransformedShapeBrush); }
效果图:
注意: 对一个对象执行多个变换意味着将多个变换组合为一个。即,将每个变换矩阵的输出用作下一个的输入,从而获得所有矩阵变换的累积效果。
假设将两个变换矩阵(旋转和平移)相乘。结果是一个新的矩阵,同时执行旋转和平移功能。因为矩阵乘法不是可交换的,所以乘以平移变换的旋转变换与乘以旋转变换的平移变换是不同的。
这也就是我每应用一个效果后,都会将其注释的原因。
有专门的文档来介绍了这部分:如何将多个变换应用于对象