• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
hhdllhflower
博客园    首页    新随笔    联系   管理    订阅  订阅

Direct2D入门

一. 资源管理(Resource management)

和Direct3D一样,Direct2D程序需要处理设备丢失(Device lost)问题。Direct2D中的资源分为设备独立资源(Device independent resource)和设备依赖资源(Device dependent resource)。

设备独立资源包括:

  • ID2D1DrawingStateBlock
  • ID2D1Factory
  • ID2D1Geometry 和由此继承而来的接口
  • ID2D1GeometrySink and ID2D1SimplifiedGeometrySink
  • ID2D1StrokeStyle

设备依赖资源包括:

  • ID2D1Brush 和由此继承而来的接口
  • ID2D1Layer
  • ID2D1RenderTarget 和由此继承而来的接口
  • 其他资源

具体参见:http://msdn.microsoft.com/en-us/library/dd756757(v=VS.85).aspx

二. Direct2D程序的结构

  1. 在程序初始化函数处创建设备独立资源,如ID2D1Factory,IDWriteFactory等;
  2. 创建设备依赖资源,如果运行过程中出现设备丢失,需要重新创建;
  3. 响应WM_PAINT消息,在OnPaint()或OnDraw()等处,用创建的资源Render;
  4. 响应WM_SIZE消息,在OnSize()处调用ID2D1RenderTarget::Resize();
  1. 响应WM_ERASEBKGND,在OnEraseBkgnd()处返回FALSE,阻止GDI重绘客户区背景色,设置背景色的工作交给Direct2D在Render时设置,否则在Resize时会出现窗口闪烁的问题;
  1. 退出程序前,清理资源。

为提高程序的性能,尽量减少资源的创建和销毁操作,将能够重复利用的资源接口变量申明为View类的成员变量。

三. Direct2D demo

一个简单的MFC程序,用于演示Direct2D程序的结构和一些简单绘图操作。

1.Direct2D prerequisite

D2dPrerequisite.h,包含一些编译Direct2D程序所需要用到的头文件,lib库文件,帮助宏和预处理指令:

 

  1: //D2dPrerequisite.h

  2: #pragma once

  3:

  4: //////////////////////////////////////////////////////////////////////////

  5: //Header files and lib files for Direct2D and DirectWrite

  6: #include <d2d1.h>                //Direct2D,for normal rendering task

  7: #include <d2d1helper.h>        

  8: #include <dwrite.h>                //DirectWrite,for drawing text

  9: #include <wincodec.h>                //Windows imaging component,for image decoding

 10:

 11: #pragma comment(lib,"d2d1.lib")

 12: #pragma comment(lib,"dwrite.lib")

 13: #pragma comment(lib,"windowscodecs.lib")

 14:

 15: //////////////////////////////////////////////////////////////////////////

 16: //Helper template for resource releasing

 17: template<class Interface>

 18: inlinevoid SafeRelease(Interface **ppInterfaceToRelease)

 19: {

 20:         if (*ppInterfaceToRelease != NULL)

 21:         {

 22:                 (*ppInterfaceToRelease)->Release();

 23:                 (*ppInterfaceToRelease) = NULL;

 24:         }

 25: }

 26:

 27: #ifndef Assert

 28: #if defined( DEBUG ) || defined( _DEBUG )

 29: #define Assert(b) do {if (!(b)) {OutputDebugStringA("Assert: " #b "\n");}} while(0)

 30: #else

 31: #define Assert(b)

 32: #endif //DEBUG || _DEBUG

 33: #endif

 34:

 35: #ifndef HINST_THISCOMPONENT

 36: EXTERN_C IMAGE_DOS_HEADER __ImageBase;

 37: #define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)

 38: #endif

2.View类中的成员变量:

 

  1: //View.h

  2: private:

  3:         //Direct2D interface

  4:         ID2D1Factory* m_pD2d1Factory;

  5:         ID2D1HwndRenderTarget* m_pHwndRenderTarget;

  6:         ID2D1SolidColorBrush* m_pSolidColorBrush;

  7:         ID2D1LinearGradientBrush* m_pLinearGradientBrush;

  8:         ID2D1RadialGradientBrush* m_pRadialGradientBrush;

  9:

 10:         //DirectWrite interface

 11:         IDWriteFactory* m_pDWriteFactory;

 12:         IDWriteTextFormat* m_pTextFormat;

3.创建设备独立资源

 

  1: //View.cpp

  2: BOOL CBasicView::CreateDeviceIndependentResource()

  3: {

  4:         HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,&m_pD2d1Factory);

  5:         ASSERT(hr == S_OK);

  6:

  7:         if (SUCCEEDED(hr))

  8:         {

  9:                 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,

 10:                         __uuidof(m_pDWriteFactory),

 11:                         reinterpret_cast<IUnknown**>(&m_pDWriteFactory));

 12:                 ASSERT(hr == S_OK);

 13:         }

 14:         

 15:         //Create TextFormat object with IDWriteFactory

 16:         if (SUCCEEDED(hr))

 17:         {

 18:                 const CString fontName = _T("Verdana");

 19:                 const FLOAT fontSize = 32.0f;

 20:                 hr = m_pDWriteFactory->CreateTextFormat(

 21:                         fontName,

 22:                         NULL,

 23:                         DWRITE_FONT_WEIGHT_NORMAL,

 24:                         DWRITE_FONT_STYLE_NORMAL,

 25:                         DWRITE_FONT_STRETCH_NORMAL,

 26:                         fontSize,

 27:                         L"",        //locale

 28:                         &m_pTextFormat

 29:                         );

 30:                 ASSERT(hr == S_OK);

 31:                 if (SUCCEEDED(hr))

 32:                 {

 33:                         //Center alignment vertically and horizontally

 34:                         m_pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);

 35:                         m_pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);

 36:                 }

 37:         }

 38:         return (hr == S_OK);

 39: }

4.创建设备依赖资源

 

  1: //View.cpp

  2: BOOL CBasicView::CreateDeviceDependentResource()

  3: {

  4:         ASSERT(m_pD2d1Factory != NULL);

  5:         if (m_pHwndRenderTarget != NULL)        //There is no need to create render target

  6:                 return TRUE;

  7:

  8:         RECT rc;

  9:         GetClientRect(&rc);

 10:         D2D1_SIZE_U size = SizeU(rc.right-rc.left,rc.bottom-rc.top);

 11:         HRESULT hr = m_pD2d1Factory->CreateHwndRenderTarget(

 12:                 RenderTargetProperties(),

 13:                 HwndRenderTargetProperties(m_hWnd,size),//Bind the HwndRenderTarget to view window

 14:                 &m_pHwndRenderTarget);

 15:         ASSERT(hr == S_OK);

 16:         if (SUCCEEDED(hr))

 17:         {

 18:                 //Create solid color brush

 19:                 hr = m_pHwndRenderTarget->CreateSolidColorBrush(

 20:                         ColorF(ColorF::LightGreen),

 21:                         &m_pSolidColorBrush);

 22:                 ASSERT(hr == S_OK);

 23:

 24:                 //Create gradient stops collection,

 25:                 //used by linear gradient brush or radial gradient brush

 26:                 ID2D1GradientStopCollection* pGradientStops = NULL;

 27:                 D2D1_GRADIENT_STOP stops[2];

 28:                 stops[0].color = ColorF(ColorF::Yellow);

 29:                 stops[0].position = 0.0f;

 30:                 stops[1].color = ColorF(ColorF::Red);

 31:                 stops[1].position = 1.0f;

 32:                 HRESULT hr = m_pHwndRenderTarget->CreateGradientStopCollection(

 33:                         stops,

 34:                         2,

 35:                         D2D1_GAMMA_2_2,

 36:                         D2D1_EXTEND_MODE_CLAMP,

 37:                         &pGradientStops);

 38:                 ASSERT(hr == S_OK);

 39:

 40:                 //Create linear gradient brush

 41:                 hr = m_pHwndRenderTarget->CreateLinearGradientBrush(

 42:                         LinearGradientBrushProperties(Point2F(210,110),Point2F(290,190)),

 43:                         pGradientStops,

 44:                         &m_pLinearGradientBrush);

 45:                 ASSERT(hr == S_OK);

 46:

 47:                 //Create radial gradient brush

 48:                 hr = m_pHwndRenderTarget->CreateRadialGradientBrush(

 49:                         RadialGradientBrushProperties(Point2F(350,150),Point2F(0,0),50,50),

 50:                         pGradientStops,

 51:                         &m_pRadialGradientBrush);

 52:                 ASSERT(hr == S_OK);

 53:

 54:                 SafeRelease(&pGradientStops);

 55:         }

 56:         

 57:         return (hr == S_OK);

 58: }

5.Render

 

  1: //View.cpp

  2: void CBasicView::Render()

  3: {

  4:         ASSERT(m_pD2d1Factory != NULL);

  5:         if (!m_pHwndRenderTarget)        //Render target need to be recreated

  6:         {

  7:                 //Recreate device dependent resource

  8:                 BOOL succeeded = CreateDeviceDependentResource();

  9:                 if (!succeeded)

 10:                         return;

 11:         }

 12:         

 13:         const D2D1_COLOR_F redColor = ColorF(ColorF::Red);

 14:         const D2D1_COLOR_F greenColor = ColorF(ColorF::Green);

 15:         const D2D1_COLOR_F blueColor = ColorF(ColorF::Blue);

 16:         const D2D1_COLOR_F yellowColor = ColorF(ColorF::Yellow);

 17:         const D2D1_COLOR_F pinkColor = ColorF(ColorF::Pink);

 18:         const D2D1_COLOR_F lightBlue = ColorF(ColorF::LightBlue);

 19:         const D2D1_COLOR_F lightGreen = ColorF(ColorF::LightGreen);

 20:

 21:         m_pHwndRenderTarget->BeginDraw();

 22:         m_pHwndRenderTarget->Clear(ColorF(ColorF::White));        //Clear the background

 23:         

 24:         //Draw line

 25:         //We can set the color and opacity of solid color brush at any time,

 26:         //so there is no need to create brushes for different colors

 27:         m_pSolidColorBrush->SetColor(redColor);        

 28:         D2D1_POINT_2F startPoint = Point2F(10,10);

 29:         D2D1_POINT_2F endPoint = Point2F(90,90);

 30:         m_pHwndRenderTarget->DrawLine(startPoint,endPoint,m_pSolidColorBrush,5.0);

 31:

 32:         //Draw rectangle

 33:         m_pSolidColorBrush->SetColor(greenColor);

 34:         D2D1_RECT_F rect = RectF(110,10,190,90);

 35:         m_pHwndRenderTarget->DrawRectangle(rect,m_pSolidColorBrush,4.0f);

 36:

 37:         //Draw rounded rectangle

 38:         m_pSolidColorBrush->SetColor(blueColor);

 39:         rect = RectF(210,10,290,90);

 40:         D2D1_ROUNDED_RECT roundedRect = RoundedRect(rect,10,10);

 41:         m_pHwndRenderTarget->DrawRoundedRectangle(roundedRect,m_pSolidColorBrush,3.0f);

 42:

 43:         //Draw ellipse

 44:         m_pSolidColorBrush->SetColor(redColor);

 45:         D2D1_POINT_2F center = D2D1::Point2F(350,50);

 46:         D2D1_ELLIPSE ellipse = D2D1::Ellipse(center,40,30);

 47:         m_pHwndRenderTarget->DrawEllipse(ellipse,m_pSolidColorBrush,3.0f);

 48:

 49:         //Fill rectangle

 50:         m_pSolidColorBrush->SetColor(pinkColor);

 51:         rect = RectF(10,110,90,190);

 52:         m_pHwndRenderTarget->FillRectangle(rect,m_pSolidColorBrush);

 53:

 54:         //Fill rounded rectangle

 55:         m_pSolidColorBrush->SetColor(blueColor);

 56:         m_pSolidColorBrush->SetOpacity(0.3f);

 57:         rect = RectF(110,110,190,190);

 58:         roundedRect = RoundedRect(rect,20,20);

 59:         m_pHwndRenderTarget->FillRoundedRectangle(roundedRect,m_pSolidColorBrush);

 60:

 61:         //Fill rectangle with linear gradient brush

 62:         rect = RectF(210,110,290,190);

 63:         m_pHwndRenderTarget->FillRectangle(rect,m_pLinearGradientBrush);

 64:         

 65:         //Fill ellipse with gradient brush

 66:         ellipse = D2D1::Ellipse(Point2F(350,150),40,40);

 67:         m_pHwndRenderTarget->FillEllipse(ellipse,m_pRadialGradientBrush);

 68:

 69:         //Draw text with a linear gradient brush

 70:         const CString text = _T("Text drawed with Direct2D & DWrite!");

 71:         rect = RectF(20,210,380,290);

 72:         m_pHwndRenderTarget->DrawTextW(

 73:                 text,

 74:                 text.GetLength(),

 75:                 m_pTextFormat,

 76:                 rect,

 77:                 m_pLinearGradientBrush);

 78:

 79:         HRESULT hr = m_pHwndRenderTarget->EndDraw();

 80:

 81:         if (hr == D2DERR_RECREATE_TARGET)        //Render target need to be recreated

 82:         {

 83:                 //Discard all device dependent resources,

 84:                 //and recreate them in the next render procedure

 85:                 DiscardDeviceDependentResource();

 86:         }

 87: }

6. 销毁设备依赖资源,以备下次Render时再次创建

 

  1: //View.cpp

  2: void CBasicView::DiscardDeviceDependentResource()

  3: {

  4:         SafeRelease(&m_pRadialGradientBrush);

  5:         SafeRelease(&m_pLinearGradientBrush);

  6:         SafeRelease(&m_pSolidColorBrush);

  7:         SafeRelease(&m_pHwndRenderTarget);

  8: }

7.Resize

 

  1: //View.cpp

  2: void CBasicView::Resize(int width,int height)

  3: {

  4:         if (m_pHwndRenderTarget)

  5:         {

  6:                 m_pHwndRenderTarget->Resize(SizeU(width,height));

  7:         }

  8: }

posted @ 2012-10-04 20:02  hhdllhflower  阅读(550)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3