使用d2d绘图
d2d初始化时,需要:
- ID2D1Factory*类型的对象,也就是D2D工厂接口,这个接口是所有D2D程序的起始点,几乎所有的D2D资源都是由这个接口创建;
- Render Target,在D2D中有多种类型的Render Target,这里我们选择ID2D1HwndRenderTarget类型,用来在窗口中进行渲染;
- Brush,用来绘制图形,这里选择固定颜色的画刷,即ID2D1SolidColorBrush。
注意头文件需要引入<d2d1.h>包含文件,并链接相关库。
//Direct2D 头文件
#include <wrl/client.h>
#include <d2d1.h>
//链接相关库
#pragma comment(lib,"d2d1.lib")
这里 <wrl/client.h>
的用处是引入微软自己提供的Comptr智能指针库,方便内存的管理,具体使用方式可以参考
DirectX11--ComPtr智能指针
这里用到的D2D资源文件全部在WindowsApp类中声明,如下:
~~~c++
//声明d2d所需指针
template
using ComPtr = Microsoft::WRL::ComPtr
ComPtr<ID2D1Factory> m_pFactory;
ComPtr<ID2D1HwndRenderTarget> m_pRenderTarget;
ComPtr<ID2D1SolidColorBrush> m_pLightSlateGrayBrush;
ComPtr<ID2D1SolidColorBrush> m_pCornflowerBlueBrush;
~~~
在WindowsApp类中新建方法 InitDirect2D() 来初始化d2d,并在其中初始化d2d资源,最后通过Init()来调用此方法。
//初始化Direct2D所需资源
bool WindowsApp::InitDirect2D() {
HRESULT hr;
//创建工厂
//参数1 ,工厂类型,单线程or多线程 参数2 ,工厂地址
hr=D2D1CreateFactory( D2D1_FACTORY_TYPE_SINGLE_THREADED, m_pFactory.GetAddressOf() );
if (FAILED(hr)){
MessageBox( 0, L"Create Factory Failed!", L"Error", 0 );
return false;
}
//创建RenderTarget
//参数1:属性,包括渲染模式,像素格式,DPI等。这里使用默认
//参数2:Size
//参数3:RenderTarget地址
hr = m_pFactory->CreateHwndRenderTarget( D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties( m_hMainWnd, D2D1::SizeU( m_ClientWidth, m_ClientHeight ) ),
m_pRenderTarget.GetAddressOf() );
if (FAILED(hr)){
MessageBox( 0, L"Create RenderTarget Failed!", L"Error", 0 );
return false;
}
//创建两个笔刷
hr = m_pRenderTarget->CreateSolidColorBrush( D2D1::ColorF( D2D1::ColorF::LightSlateGray ), m_pLightSlateGrayBrush.GetAddressOf() );
hr = m_pRenderTarget->CreateSolidColorBrush( D2D1::ColorF( D2D1::ColorF::CornflowerBlue ), m_pCornflowerBlueBrush.GetAddressOf() );
if ( FAILED( hr ) ) {
MessageBox( 0, L"Create brush failed!", L"Error", 0 );
return false;
}
return true;
}
在WindowsApp类中新建方法 DrawScene() 来使用创建的资源进行绘图,并在Run()中调用DrawScene();
void WindowsApp::DrawScene() {
HRESULT hr;
m_pRenderTarget->BeginDraw();
//设置背景颜色
m_pRenderTarget->Clear( D2D1::ColorF( D2D1::ColorF::White ) );
//绘制灰色背景
int width = m_ClientWidth;
int height = m_ClientHeight;
for ( int x = 0; x < width;x+=10 ) {
m_pRenderTarget->DrawLine( D2D1::Point2F( static_cast<FLOAT>( x ), 0.0f ), D2D1::Point2F( static_cast<FLOAT>( x ), height ), m_pLightSlateGrayBrush.Get(), 0.5f );
}
for ( int y = 0; y < height; y += 10 ) {
m_pRenderTarget->DrawLine( D2D1::Point2F( 0.0f,static_cast < FLOAT > ( y ) ), D2D1::Point2F( width,static_cast<FLOAT>( y ) ), m_pLightSlateGrayBrush.Get(), 0.5f );
}
//绘制两个矩形
D2D1_RECT_F rectangle1 = D2D1::RectF(width / 2 - 50.0f, height / 2 - 50.0f,width / 2 + 50.0f, height / 2 + 50.0f );
D2D1_RECT_F rectangle2 = D2D1::RectF( width / 2 - 100.0f,height / 2 - 100.0f,width / 2 + 100.0f, height / 2 + 100.0f );
// draw a filled rectangle
m_pRenderTarget->FillRectangle( &rectangle1, m_pLightSlateGrayBrush.Get() );
// draw a outline only rectangle
m_pRenderTarget->DrawRectangle( &rectangle2, m_pCornflowerBlueBrush.Get() );
hr = m_pRenderTarget->EndDraw();
// FinalizeDirect2D();
}
Run():
//返回值为应用程序退出返回值
int WindowsApp::Run() {
MSG msg = {0};
while ( msg.message != WM_QUIT ) {
if ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) {
//目前无用户输入,所以不需要Translate
// TranslateMessage( &msg );
DispatchMessage( &msg );
} else {
if ( !m_AppPaused ) {
DrawScene();
}
}
}
//如果消息为退出,释放资源
FinalizeDirect2D();
return (int) msg.wParam;
}
用md中代码块的话不知道为什么代码排版很奇怪,源码地址
运行结果:
参考文章: