D2D第一个程序详解

1程序框架

(1)包含D2D头文件

#include <windows.h>
#include 
<D2D1.h>

(2)创建D2D工厂  ID2D1Factory,使用 ID2D1Factory 可创建 Direct2D 资源。


此处还要声明对象:首先我们需要一ID2D1Factory*类型的对象,也就是D2D工厂接口,这个接口是所有D2D程序的起始点,几乎所有的D2D资源都是由这个接口创建的,其次我们需要一个渲染的场所,也就是Render Target,在D2D中有多种类型的Render Target,这里我们选择ID2D1HwndRenderTarget类型,用来在窗口中进行渲染。最后我们定义一个画刷,用来绘制图形,这里选择固定颜色的画刷,即ID2D1SolidColorBrush。 


ID2D1Factory* pD2DFactory = NULL ; // Direct2D factory
ID2D1HwndRenderTarget* pRenderTarget = NULL;   // Render target
ID2D1SolidColorBrush* pBlackBrush = NULL ; // A black brush, reflect the line color

RECT rc ; 
// Render area定义一个矩形
HWND g_Hwnd ; // Window handle定义一个窗口句柄


接下来创建D2D工厂对象,有了这个对象才能创建后续的资源,这个函数有两个参数,第一个参数是工厂的类型,这里只有单线程和多线程两类,如果是单线程的话,意味着D2D不会为所创建的工厂的对象以及由这个对象创建的子对象提供同步机制,也就是说,如果有多个线程访问了这个资源,那么需要自己提供同步机制。如果是多线程类型,那么D2D会为你提供同步机制。第二个参数用来接收创建的工厂。

HRESULT hr ;

hr 
= D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory) ;
if (FAILED(hr))
{
  MessageBox(hWnd, 
"Create D2D factory failed!""Error"0) ;
  
return ;
}

D2D工厂中 包含一系列的CREATE的函数什么的



(3)创建渲染目标IDWD1HwndRenderTarget

有了工厂对象以后,开始创建RenderTarget,CreateHwndRenderTarget函数有三个参数,第一个参数是Render target属性,包括渲染模式,象素格式,DPI等,D2D提供了一个函数D2D1::RenderTargetProperties(),可以用来生成默认的属性,我们这里直接使用这个函数。第二个参数是Hwnd类型的Render target属性,它包含三个参数,第一个是窗口句柄,第二个是Render target的大小,第三个参数是Present选项,这个参数有个默认值,这里我们使用它的默认值。CreateHwndRenderTarget函数的最后一个参数用来接收创建的Render target。

复制代码
// Create a Direct2D render target
hr = pD2DFactory->CreateHwndRenderTarget(
  D2D1::RenderTargetProperties(),
  D2D1::HwndRenderTargetProperties(
    hWnd, 
    D2D1::SizeU(rc.right 
- rc.left,rc.bottom - rc.top)
  ), 
  
&pRenderTarget
) ;
if (FAILED(hr))
{
  MessageBox(hWnd, 
"Create render target failed!""Error"0) ;
  
return ;
}


(4)创建绘制资源(这以创建BRUSH为例)

有了Render target,再使用函数CreateSolidColorBrush创建画刷,这里创建一个固定颜色的画刷,第一个参数是画刷的颜色,第二个参数接收创建的画刷,画刷的颜色就是绘制线条所用的颜色,比如这里创建一个红色的画刷,那么后面绘制的矩形就是红色的。

复制代码
// Create a brush
hr = pRenderTarget->CreateSolidColorBrush(
  D2D1::ColorF(D2D1::ColorF::Red),
  
&pBlackBrush
) ;
if (FAILED(hr))
{
  MessageBox(hWnd, 
"Create brush failed!""Error"0) ;
  
return ;
}
复制代码

(5)绘制

万事俱备,只欠渲染!渲染的代码很简单,首先调用CreateD2DResource函数来创建资源,这是个自定义函数,用来创建资源,比如Render target,画刷之类的,该函数包含了上面提到的代码。绘制的代码要放在BeginDraw和EndDraw函数之间,调用Clear函数可以将Render target清除为指定的背景色。DrawRectangle函数用来绘制矩形,它有两个参数,第一个是被绘制的矩形,第二个是绘制所用的画刷。函数EndDraw的返回值标识了渲染是否成功。

复制代码
VOID DrawRectangle()
{
  CreateD2DResource(g_Hwnd) ;

  pRenderTarget
->BeginDraw() ;

  
// Clear background color white
  pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));

  
// Draw Rectangle
  pRenderTarget->DrawRectangle(
  D2D1::RectF(
100.f, 100.f, 500.f, 500.f),
  pBlackBrush
);

HRESULT hr 
= pRenderTarget->EndDraw() ;

if (FAILED(hr))
{
  MessageBox(NULL, 
"Draw failed!""Error"0) ;
  
return ;
}
复制代码

(6)最后释放资源

最后,在程序退出时,清理程序资源,每个COM对象都有一个Release方法,用来释放自己,这里我们定义一个宏来释放COM对象。

VOID Cleanup()
{
  SAFE_RELEASE(pRenderTarget) ;
  SAFE_RELEASE(pBlackBrush) ;
  SAFE_RELEASE(pD2DFactory) ;
}

释放COM对象的宏。

#define SAFE_RELEASE(P) if(P){P->Release() ; P = NULL ;}

总的 程序

#include
#include


#define SAFE_RELEASE(P) if(P){P->Release() ; P = NULL ;}//定义一个释放资源的宏


ID2D1Factory* g_pD2DFactory = NULL; // Direct2D factory定义一个D2D工厂接口,该接口是D2D的起点
ID2D1HwndRenderTarget* g_pRenderTarget = NULL; // 定义一个渲染目标,为窗口类
ID2D1SolidColorBrush* g_pBlackBrush = NULL; // 定义一个固定颜色的笔刷
ID2D1SolidColorBrush*    g_pBlueBrush   = NULL;
VOID CreateD2DResource(HWND hWnd)
{
if (!g_pRenderTarget)//如果rendertarget为空
{
HRESULT hr ;


hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &g_pD2DFactory) ;//创建工厂(参数第一个是工厂的类型表示单线程还是多线程,第二个用来接收创建的工厂)
if (FAILED(hr))
{
MessageBox(hWnd, L"Create D2D factory failed!", L"Error", 0) ;//表示创建工厂失败则输出创建按工厂失败
return ;
}


// Obtain the size of the drawing area
RECT rc ;//定义一个矩形
//rect结构定义了一个矩形框左上角以及右下角的坐标,RECT结构通常用于Windows编程。
//typedef struct _RECT {
//LONG left;指定矩形框左上角的x坐标
//LONG top;指定矩形框左上角的y坐标
//LONG right;指定矩形框右下角的x坐标
//LONG bottom;指定矩形框右下角的y坐标
//} RECT, *PRECT;
        GetClientRect(hWnd, &rc) ;


// Create a Direct2D render target
hr = g_pD2DFactory->CreateHwndRenderTarget(//三个参数
D2D1::RenderTargetProperties(),//第一个参数,用默认的D2D这个函数来生成这个参数,表示渲染参数,DPI第二个惨
D2D1::HwndRenderTargetProperties(//第二个参数
hWnd, //窗口句柄
D2D1::SizeU(rc.right - rc.left,rc.bottom - rc.top)//rendertarget的大小,两个参数为窗口的长和宽
), 
&g_pRenderTarget//第三个参数,接收创建的rendertarget
) ;
if (FAILED(hr))
{
MessageBox(hWnd, L"Create render target failed!", L"Error", 0) ;//创建失败输出创建失败
return ;
}


// Create a brush
hr = g_pRenderTarget->CreateSolidColorBrush(//这里注意下创建笔刷是在rendertarget下的
D2D1::ColorF(D2D1::ColorF::Black),//第一个参数表示颜色
&g_pBlackBrush//第二个参数接收创建的画刷
) ;
if (FAILED(hr))
{
MessageBox(hWnd, L"Create brush failed!", L"Error", 0) ;//创建失败,输出创建画刷失败
return ;
}
hr = g_pRenderTarget->CreateSolidColorBrush(//这里注意下创建笔刷是在rendertarget下的
D2D1::ColorF(D2D1::ColorF::Blue),//第一个参数表示颜色
&g_pBlueBrush//第二个参数接收创建的画刷
) ;
if (FAILED(hr))
{
MessageBox(hWnd, L"Create brush failed!", L"Error", 0) ;//创建失败,输出创建画刷失败
return ;
}
}
}


VOID DrawRectangle(HWND hwnd)//渲染的函数
{
CreateD2DResource(hwnd) ;//调用上一个函数来创建资源


g_pRenderTarget->BeginDraw() ;//绘制是在begindraw和enddraw之间


// Clear background color to White
g_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Yellow));//clear函数是将绘制区域清除为一个颜色


// Draw Rectangle
g_pRenderTarget->DrawRectangle(//绘制矩形
D2D1::RectF(100.f, 100.f, 500.f, 500.f),//被绘制的矩形的大小,100,500是长宽的数值,单位是像素
g_pBlueBrush//绘制的画刷
);


HRESULT hr = g_pRenderTarget->EndDraw() ;//结束绘制
if (FAILED(hr))
{
MessageBox(NULL, L"Draw failed!", L"Error", 0) ;
return ;
}
}


VOID Cleanup()//用定义的宏释放资源
{
SAFE_RELEASE(g_pRenderTarget) ;
SAFE_RELEASE(g_pBlackBrush) ;
SAFE_RELEASE(g_pD2DFactory) ;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)   //消息响应函数
{
    switch (message)    
    {
case   WM_PAINT:
DrawRectangle(hwnd) ;//在WM_PAINT里绘制
return 0 ;


case WM_KEYDOWN: 

switch( wParam ) 

case VK_ESCAPE: 
SendMessage( hwnd, WM_CLOSE, 0, 0 ); 
break ; 
default: 
break ; 


break ; 


case WM_DESTROY: 
Cleanup(); 
PostQuitMessage( 0 ); 
return 0; 
    }


return DefWindowProc (hwnd, message, wParam, lParam) ;
}


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow )
{
        
    WNDCLASSEX winClass ;


winClass.lpszClassName = L"Direct2D";
winClass.cbSize        = sizeof(WNDCLASSEX);
winClass.style         = CS_HREDRAW | CS_VREDRAW;
winClass.lpfnWndProc   = WndProc;
winClass.hInstance     = hInstance;
winClass.hIcon        = NULL ;
winClass.hIconSm    = NULL ;
winClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
winClass.hbrBackground = NULL ;
winClass.lpszMenuName  = NULL;
winClass.cbClsExtra    = 0;
winClass.cbWndExtra    = 0;

if (!RegisterClassEx (&winClass))   
{
MessageBox ( NULL, TEXT( "This program requires Windows NT!" ), L"error", MB_ICONERROR) ;
return 0 ;  
    }   
    
HWND hwnd = CreateWindowEx(NULL,  
L"Direct2D", // window class name
L"Draw Rectangle", // window caption
WS_OVERLAPPEDWINDOW,  // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
600, // initial x size
600, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters


        ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;


MSG    msg ;  
ZeroMemory(&msg, sizeof(msg)) ;


while (GetMessage (&msg, NULL, 0, 0))  
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}


return msg.wParam ;
}

你可能感兴趣的:(D2D)