directdraw 2D example code

다이얼로그 박스에 그림을 그릴 때 DC대신 directdraw를 사용한 간단한 예제다. 

1.다이얼로그 박스에 picture control을 추가한다. 



2. CStatic을 기본으로 하는 mfc class를 생성한다. 

DDraw2DCtrl.h

class CDDraw2DCtrl : public CStatic
{
       DECLARE_DYNAMIC(CDDraw2DCtrl)

private:
       user_lock                  m_lock;

       ID2D1Factory               *m_pD2DFactory;
       IDWriteFactory             *m_pDWriteFactory;
       ID2D1HwndRenderTarget       *m_pRenderTarget;
       ID2D1SolidColorBrush        *m_pBrush;
       IDWriteTextFormat           *m_pTextFormat;

       void DestoryD2D();
       BOOL CreateD2D();
       void Draw();

public:
       CDDraw2DCtrl();
       virtual ~CDDraw2DCtrl();

       afx_msg void OnPaint();
       afx_msg BOOL OnEraseBkgnd(CDC* pDC);
protected:
       DECLARE_MESSAGE_MAP()
};


DDraw2DCtrl.cpp

#include "stdafx.h"
#include "DDraw2DCtrl.h"

#ifndef SAFE_RELEASE
#define SAFE_RELEASE(x) if (x) { x->Release(); x = NULL;}
#endif

// CDDraw2DCtrl

IMPLEMENT_DYNAMIC(CDDraw2DCtrl, CStatic)

CDDraw2DCtrl::CDDraw2DCtrl()
{
       m_pD2DFactory = NULL;
       m_pDWriteFactory = NULL;
       m_pRenderTarget = NULL;
       m_pBrush = NULL;
       m_pTextFormat = NULL;
}

CDDraw2DCtrl::~CDDraw2DCtrl()
{
       DestoryD2D();
}


BEGIN_MESSAGE_MAP(CDDraw2DCtrl, CStatic)
       ON_WM_PAINT()
       ON_WM_ERASEBKGND()
END_MESSAGE_MAP()


// CDDraw2DCtrl 메시지 처리기입니다.

void CDDraw2DCtrl::OnPaint()
{
       CPaintDC dc(this); // device context for painting
       // TODO: Add your message handler code here
       // Do not call CStatic::OnPaint() for painting messages
       CUserAutoLock lock(&m_lock);
       Draw();
}

BOOL CDDraw2DCtrl::OnEraseBkgnd(CDC* pDC)
{
       return TRUE;
       //return CStatic::OnEraseBkgnd(pDC);
}

void CDDraw2DCtrl::DestoryD2D()
{
       SAFE_RELEASE(m_pBrush);
       SAFE_RELEASE(m_pTextFormat);
       SAFE_RELEASE(m_pRenderTarget);
       SAFE_RELEASE(m_pDWriteFactory);
       SAFE_RELEASE(m_pD2DFactory);
}

BOOL CDDraw2DCtrl::CreateD2D()
{
       HRESULT hr;
       RECT rc;

       if (m_pD2DFactory || !GetSafeHwnd())
             return FALSE;

       hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);
       if (FAILED(hr))
       {
             MessageBox(TEXT("D2D1CreateFactory fail"));
             return FALSE;
       }

       GetClientRect(&rc);

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

       hr = m_pD2DFactory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(),
             D2D1::HwndRenderTargetProperties(GetSafeHwnd(), size),
             &m_pRenderTarget);

       if (FAILED(hr))
       {
             MessageBox(TEXT("m_pD2DFactory->CreateHwndRenderTarget fail"));
             DestoryD2D();
             return FALSE;
       }

       hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED,
             __uuidof(m_pDWriteFactory),
             reinterpret_cast<IUnknown **>(&m_pDWriteFactory)
             );

       if (FAILED(hr))
       {
             MessageBox(TEXT("DWriteCreateFactory fail"));
             DestoryD2D();
             return FALSE;
       }

       hr = m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &m_pBrush);
       if (FAILED(hr))
       {
             MessageBox(TEXT("m_pD2DFactory->CreateSolidColorBrush fail"));
             DestoryD2D();
             return FALSE;
       }

       hr = m_pDWriteFactory->CreateTextFormat(TEXT("Consolas"),
             NULL,
             DWRITE_FONT_WEIGHT_BOLD,
             DWRITE_FONT_STYLE_NORMAL,
             DWRITE_FONT_STRETCH_NORMAL,
             25,
             L"", //locale
             &m_pTextFormat
             );
       if (FAILED(hr))
       {
             MessageBox(TEXT("m_pD2DFactory->CreateSolidColorBrush fail"));
             DestoryD2D();
             return FALSE;
       }

       m_pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
       m_pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);

       return TRUE;
}

void CDDraw2DCtrl::Draw()
{
       CRect rect;
       HRESULT hr;

       if (!m_pRenderTarget)
       {
             if (!CreateD2D())
             {
                    return;
             }
       }

       // Resize
       GetClientRect(&rect);
       D2D1_SIZE_U size = D2D1::SizeU(rect.Width(), rect.Height());
       m_pRenderTarget->Resize(size);

       // Begin Draw
       m_pRenderTarget->BeginDraw();

       m_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
       m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));

       /* Draw Rect
       */
       m_pBrush->SetColor(D2D1::ColorF(D2D1::ColorF::Red));
       m_pRenderTarget->DrawRectangle(
             D2D1::RectF(rect.left + rect.Width() / 10, rect.top + rect.Height() / 10, rect.right - rect.Width() / 10, rect.bottom - rect.Height() / 10),
             m_pBrush
             );

       /*DrawText
       */
       m_pBrush->SetColor(D2D1::ColorF(D2D1::ColorF::Black));
       CString csText = TEXT("사장님 나빠요");
       m_pRenderTarget->DrawText(
             csText.GetString(),
             wcslen(csText.GetString()),
             m_pTextFormat,
             D2D1::RectF(rect.left, rect.top, rect.right, rect.bottom),
             m_pBrush
             );


       hr = m_pRenderTarget->EndDraw();
}


BOOL CreateD2D()에서 DDraw 2D관련 리소스를 생성하고, void DestoryD2D()에서 해제한다. 실제 그림을 그리는 함수는 void Draw()이다.


3. 다이얼로그 클래스에 1에서 생성한 picture control의 컨트롤 변수를 추가한다. 변수 형식은 위 2에서 만든 class를 사용한다.


4. 실행화면은 아래 그림과 같다. 1에서 생성한 picture control 윈도우에 박스와 글이 써진 것을 볼 수 있다.

댓글

이 블로그의 인기 게시물

간단한 cfar 알고리즘에 대해

windows에서 간단하게 크롬캐스트(Chromecast)를 통해 윈도우 화면 미러링 방법

쉽게 설명한 파티클 필터(particle filter) 동작 원리와 예제

base64 인코딩 디코딩 예제 c 소스

간단한 칼만 필터(Kalman Filter) 소스 코드와 사용 예제