• Direct2D入门


    . 资源管理(Resource management)

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

    设备独立资源包括:

    设备依赖资源包括:

    • 其他资源

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

    . Direct2D程序的结构

    1. 在程序初始化函数处创建设备独立资源,如ID2D1FactoryIDWriteFactory等;
    2. 创建设备依赖资源,如果运行过程中出现设备丢失,需要重新创建;
    3. 响应WM_PAINT消息,在OnPaint()OnDraw()等处,用创建的资源Render
    4. 响应WM_SIZE消息,在OnSize()处调用ID2D1RenderTarget::Resize();
    1. 响应WM_ERASEBKGND,在OnEraseBkgnd()处返回FALSE,阻止GDI重绘客户区背景色,设置背景色的工作交给Direct2DRender时设置,否则在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: }

  • 相关阅读:
    算法------------数组----------------两个数组的交集 II
    算法-----------数组------------只出现一次的数字
    算法------数组---------存在重复元素
    androd hook acitivity 启动流程,替换启动的activity(Android Instrumentation)
    算法--------旋转数组
    Android 项目,没有可运行的Module项
    Java多线程系列目录(共43篇)
    python3:tuple元组
    python 3 :list
    python3 基本数据类型
  • 原文地址:https://www.cnblogs.com/hhdllhflower/p/2711706.html
Copyright © 2020-2023  润新知