获取 BackBuffer(后台缓存) 直接描绘圆和矩形。
这回程序里的 DisplayFrame() 函数跟以前有很大不同。 DirectX 使用了 FrontBuffer(前台缓存) 和 BackBuffer(后台缓存) 至少两块 Surface(表面|描绘专用内存) 。在 FrontBuffer 中保存当前画面正在显示的图象,使用 BackBuffer 来创建下一帧将要显示的图象;然后在 BackBuffer 中的图象准备好后,将它与 FrontBuffer 瞬间切换,后台变前台、前台变后台。我们就是要获取这个 BackBuffer 来直接描绘圆和矩形。
创建窗口的代码。
"50,50,0,0" ,后面的两个零本应是窗口的宽和高,只是我们可以通过 CreateWindowedDisplay() 来重置设定,所以填上零也没问题。
WNDCLASS wc = { CS_CLASSDC,WndProc,0L,0L,hInst,
NULL,NULL,NULL,NULL,NAME };
if (RegisterClass(&wc)==0)
return FALSE;
HWND hWnd = CreateWindow(NAME,NAME,WS_OVERLAPPEDWINDOW,50,50,0,0,
GetDesktopWindow(),NULL,wc.hInstance,NULL);
if (hWnd==NULL)
return FALSE;
创建 Sueface 的代码。
按 320*240 的大小创建 FrontBuffer 和 BackBuffer 两块 Surface ;
窗口大小也设定为 320*240 :
g_pDisplay = new CDisplay();
if (FAILED(hr = g_pDisplay-CreateWindowedDisplay(hWnd,320,240)))
{
ERMSG("Failed initializing DirectDraw.");
return hr;
}
DisplayFrame() 函数。
用 g_pDisplay-Clear() 清空 BackBuffer ;
"pBack= g_pDisplay-GetBackBuffer();" 是获取 BackBuffer 的代码;
BackBuffer 由 LPDIRECTDRAWSURFACE7 定义;
说明到这里,稍有点儿 DirectX 7 经验的已经可以理解了,对于初学者还要补充几点:
获取 pBack HDC ,描绘第一个圆;
然后设定透明刷子(填充色),描绘第二个圆;
然后设定白色钢笔(边界色),描绘第一个矩形;
然后设定黑色刷子,描绘第二个矩形;
钢笔与刷子的设定使用 StockObject ;
描绘结束后释放 HDC ;
用 g_pDisplay-Present() 与前景切换:
HRESULT DisplayFrame()
{
HRESULT hr;
LPDIRECTDRAWSURFACE7 pBack;
// DirectDraw back surface
HDC
hdc;
g_pDisplay-Clear(RGB(160,140,120));
pBack= g_pDisplay-GetBackBuffer();
if (pBack-GetDC(&hdc)==DD_OK)
{
Ellipse(hdc, 50, 50, 100, 100);
//圆
SelectObject(hdc,GetStockObject(HOLLOW_BRUSH));
Ellipse(hdc, 150, 50, 200, 100);
SelectObject(hdc,GetStockObject(WHITE_PEN));
Rectangle(hdc, 50, 150, 100, 200);
//矩形
SelectObject(hdc,GetStockObject(DKGRAY_BRUSH));
Rectangle(hdc, 150, 150, 200, 200);
pBack-ReleaseDC(hdc);
}
if (FAILED(hr= g_pDisplay-Present())) return hr;
return S_OK;
}
下面说明工程的创建方法。
1.
新建一个 Win32 Application 空白工程,命名为 "Graphics"。
2.
向工程中新建一个 C++ Source File ,命名为 "graphics" ,向其中键入篇末附带的源程序。
3.
把下面4个文件复制到工程文件夹(我是 G:\DirectX 8\Graphics\):
E:\Mssdk\samples\Multimedia\Common\include\ddutil.h
E:\Mssdk\samples\Multimedia\Common\include\dxutil.h
E:\Mssdk\samples\Multimedia\Common\src\ddutil.cpp
E:\Mssdk\samples\Multimedia\Common\src\dxutil.cpp
然后选择菜单 [Project|工程]-[Add To Project|添加到工程]-[Files...|文件...] ,向工程中添加这4个文件。
4.
选择菜单 [Project|工程]-[Settings...|设定...] 打开[Project Settings|工程设定] 面板,点击 [Link|链接] 标签,向 [Object/library modules|对象、库模块] 栏内添加下面4个库文件:
dxguid.lib
ddraw.lib
dxerr8.lib
winmm.lib
5.
编译并执行!
源程序:
/*********************************************/
/*★ 描绘圆和矩形
2001-01-16
前田 稔 ★*/
/*********************************************/
#define
NAME
"Draw"
#define
STRICT
#include
#include
#include
#include
"ddutil.h"
// Defines, constants, and global variables
#define SAFE_DELETE(p)
{ if (p) { delete (p);
(p)=NULL; } }
#define SAFE_RELEASE(p) { if (p) { (p)-Release(); (p)=NULL; } }
#define ERMSG(x)
MessageBox(hWnd, x, "DirectDraw", MB_OK);
CDisplay*
g_pDisplay
= NULL;
BOOL
g_bActive
= FALSE;
// Function-prototypes
LRESULT
CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
HRESULT
InitDraw(HWND hWnd);
VOID
FreeDraw();
HRESULT
DisplayFrame();
//★ Windows Main
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow)
{
MSG
msg;
WNDCLASS wc = { CS_CLASSDC,WndProc,0L,0L,hInst,
NULL,NULL,NULL,NULL,NAME };
if (RegisterClass(&wc)==0)
return FALSE;
HWND hWnd = CreateWindow(NAME,NAME,WS_OVERLAPPEDWINDOW,50,50,0,0,
GetDesktopWindow(),NULL,wc.hInstance,NULL);
if (hWnd==NULL)
return FALSE;
if (FAILED(InitDraw(hWnd)))
{
if (g_pDisplay)
g_pDisplay-GetDirectDraw()-SetCooperativeLevel(NULL, DDSCL_NORMAL);
ERMSG("DirectDraw init failed. The sample will now exit.");
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while(TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (0 == GetMessage(&msg, NULL, 0, 0))
return (int)msg.wParam;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
if (g_bActive)
{
if (FAILED(DisplayFrame()))
{
SAFE_DELETE(g_pDisplay);
ERMSG("Displaying the next frame failed");
return FALSE;
}
}
else
WaitMessage();
}
}
}
//★ WndProc()
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_KEYDOWN:
PostMessage(hWnd,WM_CLOSE,0,0);
return 0L;
case WM_PAINT:
if (g_pDisplay)
{
if (DisplayFrame() == DDERR_SURFACELOST)
{
PostMessage(hWnd,WM_CLOSE,0,0);
}
}
break;
case WM_MOVE:
if (g_pDisplay)
g_pDisplay-UpdateBounds();
return 0L;
case WM_SIZE:
if (SIZE_MAXHIDE==wParam||SIZE_MINIMIZED==wParam)
g_bActive= FALSE;
else
g_bActive= TRUE;
if (g_pDisplay)
g_pDisplay-UpdateBounds();
break;
case WM_DESTROY:
FreeDraw();
PostQuitMessage(0);
return 0L;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
//★ InitDraw()
HRESULT InitDraw(HWND hWnd)
{
HRESULT
hr;
g_pDisplay = new CDisplay();
if (FAILED(hr = g_pDisplay-CreateWindowedDisplay(hWnd,320,240)))
{
ERMSG("Failed initializing DirectDraw.");
return hr;
}
return S_OK;
}
//★ DisplayFrame()
HRESULT DisplayFrame()
{
HRESULT hr;
LPDIRECTDRAWSURFACE7 pBack;
// DirectDraw back surface
HDC
hdc;
g_pDisplay-Clear(RGB(160,140,120));
pBack= g_pDisplay-GetBackBuffer();
if (pBack-GetDC(&hdc)==DD_OK)
{
Ellipse(hdc, 50, 50, 100, 100);
//圆
SelectObject(hdc,GetStockObject(HOLLOW_BRUSH));
Ellipse(hdc, 150, 50, 200, 100);
SelectObject(hdc,GetStockObject(WHITE_PEN));
Rectangle(hdc, 50, 150, 100, 200);
//矩形
SelectObject(hdc,GetStockObject(DKGRAY_BRUSH));
Rectangle(hdc, 150, 150, 200, 200);
pBack-ReleaseDC(hdc);
}
if (FAILED(hr= g_pDisplay-Present())) return hr;
return S_OK;
}
//★ FreeDraw()
VOID FreeDraw()
{
SAFE_DELETE(g_pDisplay);
}