您的位置:首页 > 其它

Direct2D 几何图形绘制基础

2013-07-29 20:14 281 查看
之前说过,D2D主要为了绘制有三种类型的数据:几何图形,图片,文字。这几种对象也叫做资源,资源就是要D2D流水线中要被加工的对象。

几何图形包括

简单几何图形

直线,DrawLine,由起点和终点构成,点用结构体:D2D1_POINT_2F描述。

矩形,ID2D1RectangleGeometry,DrawRectangle,由距四条边的距离表示,用结构体:D2D1_RECT_F描述。

圆角矩形,ID2D1RoundedRectangleGeometry ,DrawRoundedRectangle,同矩形,用结构体:D2D1_ROUNDED_RECT描述,另外还要加入圆角参数。

椭圆,包括圆,ID2D1EllipseGeometry ,DrawEllipse,用结构体:D2D1_ELLIPSE 描述。

路径,ID2D1PathGeometry

组合图形,

几何图形组合,ID2D1GeometryGroup

变幻几何图形,ID2D1TransformedGeometry

准备绘制:

在开始绘制之前,至少要准备好3样东西:

D2D工厂对象,ID2D1Factory接口。用于创建绘制目标,用方法CreateHwndRenderTarget。

渲染窗口,ID2D1HwndRenderTarget接口。如果是Win32程序就是默认的HWND窗口,如果是商店应用则是一个绘制表面的控件。
渲染窗口同时还负责着绘制几何图形,文字和图片。

画刷,ID2D1SolidColorBrush接口。绘制几何图形时用于指定图形的样式。

绘制区域,如果是win32程序还需要指定渲染窗口中要绘制的区域。

首先要引入头文件和命名空间:

#include "windows.h"
#include "D2D1.h"

using namespace D2D1;


别忘了加要链接的Lib,要input的lib如下:

d2d1.lib;

dxgi.lib;

dwrite.lib;

dxguid.lib;

windowscodecs.lib;

声明以上4个对象的代码如下:

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

初始化这些值的代码如下:

//create d2d factory
hr =  D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory) ;
//create render target (hwnd window)
GetClientRect(hWnd, &rc);
hr = pD2DFactory->CreateHwndRenderTarget( RenderTargetProperties(), HwndRenderTargetProperties(hWnd, SizeU(rc.right - rc.left, rc.bottom - rc.top)), &pRenderTarget);
//create brush
hr = pRenderTarget->CreateSolidColorBrush(ColorF(ColorF::Blue), &pBlackBrush);


然后就可以开始绘制了。笔者使用的程序是win32应用程序,绘制的代码都必须写在WndProc回调函数的case WM_PAINT:之后,并且要将所有绘制代码都包含在pRenderTarget->BeginDraw();和pRenderTarget->EndDraw();之间。例如:

pRenderTarget->BeginDraw();

//clear screen
pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));

//draw line with 2 points
D2D1_POINT_2F ptStart = Point2F(0,0);
D2D1_POINT_2F ptEnd = Point2F(100,100);
pRenderTarget->DrawLine(ptStart,ptEnd,pBlackBrush);

//draw rectangle
D2D1_RECT_F rect  = RectF(rc.left + 100.0f, rc.top + 100.0f, rc.right - 100.0f, rc.bottom - 100.0f);
pRenderTarget->DrawRectangle(rect, pBlackBrush);

//draw round rect
D2D1_ROUNDED_RECT roundrect  = RoundedRect(RectF(rc.left + 100.0f, rc.top + 100.0f, rc.right - 100.0f, rc.bottom - 100.0f), 30.0f, 50.0f);
pRenderTarget->DrawRoundedRectangle(roundrect, pBlackBrush, 1.0f);

pRenderTarget->EndDraw();


WM_PAINT是在窗口需要重绘时由系统调用的,所以我们不用主动地去调用它,它们不断地刷新的。

当然了,把代码都积压在WM_PAINT之后也太SB了,最好自己封装一个类,如下:

头文件如下:

#pragma once

#include "stdafx.h"
#include "windows.h" #include "D2D1.h" using namespace D2D1;

class D2DRender
{
public:
D2DRender(void);
~D2DRender(void);

HRESULT CreateDeviceIndependentResources();
HRESULT CreateDeviceResources(HWND hWnd);
void OnRender();
void DiscardDeviceResources();
void OnResize(UINT width, UINT height);

private:
// Direct2D factory
ID2D1Factory* pD2DFactory;
// Render target
ID2D1HwndRenderTarget* pRenderTarget;
// A black brush, reflect the line color
ID2D1SolidColorBrush* pBlackBrush;
// Render area
RECT rc ;
//result
HRESULT hr;
};

实现如下:

#include "stdafx.h"
#include "D2DRender.h"

D2DRender::D2DRender()
{
// Direct2D factory
pD2DFactory = NULL;
// Render target
pRenderTarget = NULL;
// A black brush, reflect the line color
pBlackBrush = NULL;
}

D2DRender::~D2DRender()
{
pD2DFactory->Release();
pRenderTarget->Release();
pBlackBrush->Release();

}

void D2DRender::DiscardDeviceResources()
{
pD2DFactory->Release();
pRenderTarget->Release();
pBlackBrush->Release();
}

void D2DRender::OnResize(UINT width, UINT height)
{
if(pRenderTarget)
{
pRenderTarget->Resize(SizeU(width,height));
}
}

HRESULT D2DRender::CreateDeviceIndependentResources()
{
//create d2d factory
hr =  D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory) ;

return hr;
}

HRESULT D2DRender::CreateDeviceResources(HWND hWnd)
{
//create render target (hwnd window)
GetClientRect(hWnd, &rc);
hr = pD2DFactory->CreateHwndRenderTarget( RenderTargetProperties(), HwndRenderTargetProperties(hWnd, SizeU(rc.right - rc.left, rc.bottom - rc.top)), &pRenderTarget);

//create brush
hr = pRenderTarget->CreateSolidColorBrush(ColorF(ColorF::Blue), &pBlackBrush);

return hr;
}

void D2DRender::OnRender()
{
pRenderTarget->BeginDraw();

//clear screen
pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));

//draw line with 2 points
D2D1_POINT_2F ptStart = Point2F(0,0);
D2D1_POINT_2F ptEnd = Point2F(100,100);
pRenderTarget->DrawLine(ptStart,ptEnd,pBlackBrush);

//draw rectangle
D2D1_RECT_F rect  = RectF(rc.left + 100.0f, rc.top + 100.0f, rc.right - 100.0f, rc.bottom - 100.0f);
pRenderTarget->DrawRectangle(rect, pBlackBrush);

//draw round rect
D2D1_ROUNDED_RECT roundrect  = RoundedRect(RectF(rc.left + 100.0f, rc.top + 100.0f, rc.right - 100.0f, rc.bottom - 100.0f), 30.0f, 50.0f);
pRenderTarget->DrawRoundedRectangle(roundrect, pBlackBrush, 1.0f);

pRenderTarget->EndDraw();
}


然后在WM_PANIT里调用,默认生成的gdi绘制用到的hdc相关代码可以删掉。

case WM_PAINT:
//hdc = BeginPaint(hWnd, &ps);
D2DRender pRender;
pRender.CreateDeviceIndependentResources();
pRender.CreateDeviceResources(hWnd);
pRender.OnRender();
//EndPaint(hWnd, &ps);
break;


还是比较简单。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: