创建图形资源后,即可绘制图形。
绘制一个椭圆
Circle程序执行非常简单的绘图逻辑:
- 用纯色填充背景。
- 画一个实心圆。
Circle程序的屏幕截图。
因为渲染目标是一个窗口(与位图或其他非屏幕表面相反),所以绘制是为了响应WM_PAINT消息而完成的。以下代码显示了Circle程序的窗口过程。
LRESULT MainWindow::HandleMessage(UINT uMsg,WPARAM wParam,LPARAM lParam){
switch(uMsg){
case WM_PAINT:
OnPaint();
return 0;
// Other messages not shown...
}
return DefWindowProc(m_hwnd,uMsg,wParam,lParam);
}
这是绘制圆的代码。
void MainWindow::OnPaint(){
HRESULT hr=CreateGraphicsResources();
if(SUCCEEDED(hr)){
PAINTSTRUCT ps;
BeginPaint(m_hwnd,&ps);
pRenderTarget->BeginDraw();
pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::SkyBlue));
pRenderTarget->FillEllipse(ellipse,pBrush);
hr=pRenderTarget->EndDraw();
if(FAILED(hr)||hr==D2DERR_RECREATE_TARGET)
DiscardGraphicsResources();
EndPaint(m_hwnd,&ps);
}
}
ID2D1RenderTarget接口用于所有绘图操作。该程序的OnPaint方法执行以下操作:
- ID2D1RenderTarget::BeginDraw方法表示绘图的开始。
- ID2D1RenderTarget::Clear方法使用纯色填充整个渲染目标。颜色以D2D1_COLOR_F结构给出。您可以使用D2D1::ColorF类来初始化结构。有关更多信息,请参阅在Direct2D中使用颜色。
- ID2D1RenderTarget::FillEllipse方法使用指定的填充画笔绘制一个填充的椭圆。椭圆由中心点和x和y半径指定。如果x和y半径相同,则结果是一个圆。
- ID2D1RenderTarget::EndDraw方法表示此帧的绘制完成。所有绘图操作必须放在对BeginDraw和EndDraw的调用之间。
BeginDraw,Clear和FillEllipse方法都有一个void返回类型。如果在执行任何这些方法的过程中发生错误,则通过EndDraw方法的返回值来指示错误。 CreateGraphicsResources方法显示在创建Direct2D资源主题中。此方法创建渲染目标和纯色画笔。
设备可能会缓冲绘图命令并推迟执行,直到调用EndDraw。您可以通过调用ID2D1RenderTarget::Flush来强制设备执行任何挂起的绘图命令。但是,冲洗会降低性能。
处理设备丢失
程序正在运行时,正在使用的图形设备可能不可用。例如,如果显示分辨率改变,或者用户移除了显示适配器,则设备可能会丢失。如果设备丢失,则渲染目标也会与设备关联的任何设备相关资源一起失效。Direct2D通过从EndDraw方法返回错误代码D2DERR_RECREATE_TARGET来指示丢失的设备。如果收到此错误代码,则必须重新创建渲染目标和所有设备相关的资源。
要放弃资源,只需释放该资源的接口即可。
void MainWindow::DiscardGraphicsResources(){
SafeRelease(&pRenderTarget);
SafeRelease(&pBrush);
}
创建资源可能是一项昂贵的操作,因此不要为每个WM_PAINT消息重新创建资源。创建资源一次,然后缓存资源指针,直到资源由于设备丢失而变为无效,或直到您不再需要该资源为止。
Direct2D渲染循环
无论你画什么,你的程序都应该执行一个类似于下面的循环。
- 创建独立于设备的资源。
- 渲染场景。
- 检查是否存在有效的渲染目标。如果没有,则创建渲染目标和设备相关的资源。
- 调用ID2D1RenderTarget::BeginDraw。
- 发出绘图命令。
- 调用ID2D1RenderTarget::EndDraw。
- 如果EndDraw返回D2DERR_RECREATE_TARGET,则放弃渲染目标和设备相关的资源。
- 无论何时需要更新或重绘场景,请重复第2步。
如果渲染目标是一个窗口,则每当窗口收到WM_PAINT消息时,就会发生第2步。
此处显示的循环通过丢弃与设备相关的资源来处理设备丢失,并在下一个循环开始时重新创建它们(步骤2-1)。
下一个
DPI和设备无关的像素