这个事例程序是本人在SDK样例程序中改写的,将其中无关的内容删除。希望对刚入门的学习者有帮助。
DirectX中的Dreaw的使用方法:
我看过几篇文章写得不错,想表达一下我的理解。
DirectX对象是对一个屏幕的控制权的操作,主要的方法有:创建,刷新,卸载。
平面(表面,缓存等几个名称)是一块显存空间,使用的平面有三种:
1、主平面(前平面),前平面是屏幕显示的内容,显卡读取主平面内容显示在屏幕上。
2、辅助平面(后平面),后平面是存放程序将要显示的内容,当辅助平面内容完成后,交换主平面与辅助平面,是屏幕
显示辅助平面的内容,不停的在辅助平面内画,不停的交换,使屏幕不出现闪烁。
3、位图(文字)平面,此平面用来将位图或文字画在一个平面内,需要时将位图或文字拷贝到辅助平面。位图(文字)
平面在创建时大小已经固定,位图平面加在的位图变化后(使用CSurface::DrawBitmap函数),如果尺寸改变,这位图
将要变形(限于此程序,此方法使StretchBlt( hDC, 0, 0, ddsd.dwWidth, ddsd.dwHeight,hDCImage, 0, 0,
bmp.bmWidth, bmp.bmHeight,SRCCOPY )位图变形),文字平面改变文字内容后(使用CSurface::DrawText函数),如果
文字变多则超出部分不能显示,如果变少则前面的文字不能覆盖,本人解决的方式是
GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); //得到显示文字的尺寸
dwHeight = sizeText.cx ; //保留字体的大小
dwHeight = sizeText.cy;
得到有效的宽度和高度,在显示时只显示有效部分
prc.top = 1;
prc.bottom = g_pTextSurface->GetHeight();
prc.left = 1;
prc.right = g_pTextSurface->GetWidth();
g_pDisplay->Blt( 10, 10, g_pTextSurface, NULL ); //在指定位置显示文字
下面我是程序
Client.cpp
#include
#include
#include "resource.h"
#include "ddutil.h"
#define SCREEN_WIDTH 800 //创建DirectX的宽度,高度,颜色深度
#define SCREEN_HEIGHT 600
#define SCREEN_BPP 16 //XXXXX(红)XXXXXX(绿)XXXXX(蓝)
#define RGB16_GREEN 0x07E0 //0000,0111,1110,0000
#define RGB16_WHITE 0xFFFF //1111,1111,1111,1111
#define RGB16_BLACK 0x0000 //0000,0000,0000,0000
#define YUNDONG_UP 1 //定义运动的方向
#define YUNDONG_DOWN 2
#define YUNDONG_LEFT 3
#define YUNDONG_RIGHT 4
#define NUM_SPRITES 1 //定义出现的精灵图像个数
struct SPRITE //定义精灵的运动结构
{
FLOAT fPosX; //出现的位置
FLOAT fPosY;
FLOAT fVelX; //水平或垂直运动的速度
FLOAT fVelY;
DWORD dwWidth; //定义的大小;
DWORD dwHeight;
INT iFangXiang; //精灵运动的方向
};
CDisplay* g_pDisplay; //创建DirectX类的实例
CSurface* g_pLogoSurface; //创建一个位图表面
CSurface* g_pTextSurface; //创建一个文字表面
SPRITE g_Sprite[NUM_SPRITES]; //创建图像精灵
DWORD g_dwLastTick ; //记录时间
BOOL g_bActive; //判断DirectX是否能活动
BOOL g_bLianJie; //跳过窗口的判断变量
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );//窗口的消息处理函数
HRESULT ProcessNextFrame(); //显示下一帧
void UpdateSprite( SPRITE* pSprite, FLOAT fTimeDelta ); //更新精灵的范围的边界情况
HRESULT DisplayFrame(); //显示帧的内容
HRESULT RestoreSurfaces(); //当平面信息丢失时更新平面的内容
VOID FreeDirectDraw(); //释放表面及DirectX实例
//
// 应用程序入口 //
//
int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow )
{
WNDCLASS wc;
HWND hWnd;
HACCEL hAccel;
MSG msg;
ZeroMemory( &g_Sprite, sizeof(SPRITE) * NUM_SPRITES );
srand( GetTickCount() );
//
// 创建游戏窗体 //
//
wc.lpszClassName = TEXT("Client"); //窗口类名称
wc.lpfnWndProc = MainWndProc; //消息处理函数
wc.style = CS_VREDRAW | CS_HREDRAW; //窗口的类型
wc.hInstance = hInst; //窗口实例(继承)
wc.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN) ); //窗口图标
wc.hCursor = LoadCursor( NULL, IDC_ARROW ); //窗口鼠标
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //窗口的背景
wc.lpszMenuName = NULL; //窗口菜单
wc.cbClsExtra = 0; //保留
wc.cbWndExtra = 0; //保留
if( RegisterClass( &wc ) == 0 ) //判断窗口类是否注册成功
return E_FAIL;
hWnd = CreateWindow( TEXT("Client"), TEXT("Client1"), //创建窗口
WS_SYSMENU | WS_MAXIMIZEBOX, 180,110,
430, 230, NULL, NULL, hInst, NULL );
if( hWnd == NULL ) //判断窗口是否创建成功
return E_FAIL;
ShowWindow( hWnd, nCmdShow ); //显示窗口
UpdateWindow( hWnd ); //更新窗口
//以下四行内容显示一个窗口,可删除
g_bLianJie = false; //设置窗口退出条件
while(GetMessage( &msg, NULL, 0, 0 ) && !g_bLianJie) //显示窗口并处理消息
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
hAccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL) ); //创建按键关联表
//
// 创建DirectDraw //
//
HRESULT hr;
g_pDisplay = new CDisplay(); //定义DirectX实例
//创建一个全屏的窗体
if( FAILED( hr = g_pDisplay->Create( hWnd, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP ) ) )
return hr;
//创建一个平面,并且在画上一个位图资源,用于显示位图
if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap(&g_pLogoSurface, MAKEINTRESOURCE( IDB_DIRECTX ), 0, 0) ) )
return hr;
//设置位图显示时的透明颜色
if( FAILED( hr = g_pLogoSurface->SetColorKey( RGB16_BLACK ) ) )
return hr;
//创建一个平面,并且在输出文字资源,用于显示文字
if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, "123456789",
RGB(0,255,0), RGB(255, 255, 0) ) ) )
return hr;
//设置文字显示时的透明颜色(应该与文字背景色一致)
if( FAILED( hr = g_pTextSurface->SetColorKey( RGB16_GREEN ) ) )
return hr;
for( int i = 0; i < NUM_SPRITES; i++ ) //定义精灵初始值
{
g_Sprite[i].fPosX = 0.0f;
g_Sprite[i].fPosY = 0.0f;
g_Sprite[i].fVelX = 0.0f;
g_Sprite[i].fVelY = 0.0f;
g_Sprite[i].dwWidth = g_pLogoSurface->GetWidth(); //得到位图平面的宽度和高度
g_Sprite[i].dwHeight = g_pLogoSurface->GetHeight();
g_Sprite[i].iFangXiang = YUNDONG_UP;
}
g_dwLastTick = timeGetTime(); //记录当前时间
while(true)//进入消息循环,以下内容不明白,请有心人帮忙解释一下
{
if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) //判断是否收到消息
{
//WM_QUIT退出消息
if( 0 == GetMessage(&msg, NULL, 0, 0 ) )
{
return (int)msg.wParam;
}
//翻译并且分派消息
if( 0 == TranslateAccelerator( hWnd, hAccel, &msg ) ) //是否是按键表对应的消息
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
else
{
if( g_bActive ) //当可以重画屏幕时
{
if( FAILED( ProcessNextFrame() ) ) //显示下一帧
return 0;
}
else
{
WaitMessage(); //等待消息
g_dwLastTick = timeGetTime();
}
}
}
return 0;
}
//
// 游戏窗体消息处理函数 //
//
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
HDC hdc;
PAINTSTRUCT ps;
switch (msg)
{
case WM_KEYDOWN: //当任意键按下时退出开始的窗口
g_bLianJie = true;
return 0L;
case WM_PAINT: //重画屏幕消息与DirectX无关
{
hdc = BeginPaint(hWnd, &ps); //得到DC
HFONT hFont = CreateFont(30,0,0,0,0,0,0,0,0,0,0,0,0,"宋体"); //创建字体
SelectObject(hdc, hFont); //设置字体
DeleteObject(hFont); //删除字体
//GetClientRect( hWnd, &rect );
SetTextColor(hdc, RGB(0, 0, 0)); //设置颜色
TextOut(hdc, 100, 50, "欢迎使用游戏", 12); //显示文字
SetTextColor(hdc, RGB(0, 0, 255));
TextOut(hdc, 100, 100, "我的DirectXDraw", 15);
EndPaint( hWnd, &ps); //删除DC
return 0L;
}
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDM_EXIT: //按键表中的退出消息
PostMessage( hWnd, WM_CLOSE, 0, 0 );
return 0L;
case IDM_UP: //按键表中的向上消息
g_Sprite[0].fVelX = 0.0f; //水平不运动
g_Sprite[0].fVelY = -100.0f; //竖直向上
g_Sprite[0].iFangXiang = YUNDONG_UP; //运动方向
break;
case IDM_DOWN: //按键表中的向下消息
g_Sprite[0].fVelX = 0.0f;
g_Sprite[0].fVelY = 100.0f;
g_Sprite[0].iFangXiang = YUNDONG_DOWN;
break;
case IDM_LEFT: //按键表中的向左消息
g_Sprite[0].fVelX = -100.0f;
g_Sprite[0].fVelY = 0.0f;
g_Sprite[0].iFangXiang = YUNDONG_LEFT;
break;
case IDM_RIGHT: //按键表中的向右消息
g_Sprite[0].fVelX = 100.0f;
g_Sprite[0].fVelY = 0.0f;
g_Sprite[0].iFangXiang = YUNDONG_RIGHT;
break;
}
break;
case WM_SIZE: //尺寸改变时
if( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam )
g_bActive = FALSE;
else
g_bActive = TRUE;
case WM_SETCURSOR: //鼠标隐藏
// Hide the cursor in fullscreen
SetCursor( NULL );
return TRUE;
case WM_SYSCOMMAND: //系统消息,不可少
switch( wParam )
{
case SC_MONITORPOWER:
return TRUE;
}
break;
case WM_DESTROY: //窗口释放消息
PostQuitMessage( 0 ); //抛出窗口退出消息
FreeDirectDraw(); //释放平面
return 0L;
}
return DefWindowProc(hWnd, msg, wParam, lParam); //系统默认详细处理
}
//
// 显示下一帧 //
//
HRESULT ProcessNextFrame()
{
HRESULT hr;
DWORD dwCurrTick = timeGetTime(); //得到当前时间
DWORD dwTickDiff = dwCurrTick - g_dwLastTick; //显示暂停时间
if( dwTickDiff == 0 ) //没有暂停退出
return S_OK;
g_dwLastTick = dwCurrTick; //重新得到当前时间
for( int i = 0; i < NUM_SPRITES; i++ )
UpdateSprite( &g_Sprite[i], dwTickDiff / 1000.0f ); //循环更新精灵的运动位置
if( FAILED( hr = DisplayFrame() ) ) //显示屏幕的内容
{
if( hr != DDERR_SURFACELOST ) //判断屏幕信息是否丢失
return hr;
RestoreSurfaces(); //重新刷新表面内容
}
return S_OK;
}
//
// 更新精灵的运动位置 //
// //
// 参数:精灵结构指针,屏幕未更新时间 //
//
void UpdateSprite( SPRITE* pSprite, FLOAT fTimeDelta )
{
pSprite->fPosX += pSprite->fVelX * fTimeDelta;//计算新的位置
pSprite->fPosY += pSprite->fVelY * fTimeDelta;
//以下判断是否超出屏幕的范围
if( pSprite->fPosX < 0.0f )
{
pSprite->fPosX = FLOAT( SCREEN_WIDTH -1 - pSprite->dwWidth/2 );
}
if( pSprite->fPosX >= SCREEN_WIDTH - pSprite->dwWidth/2 )
{
pSprite->fPosX = 0;
}
if( pSprite->fPosY < 0 )
{
pSprite->fPosY = FLOAT( SCREEN_HEIGHT - 1 - pSprite->dwHeight/2 );
}
if( pSprite->fPosY > SCREEN_HEIGHT - pSprite->dwHeight/2 )
{
pSprite->fPosY = 0;
}
}
//
// 显示帧的内容 //
//
HRESULT DisplayFrame()
{
HRESULT hr;
RECT prc;
g_pDisplay->Clear( 0x3F1F ); //使用指定的颜色覆盖屏幕
for( int i =0; i < NUM_SPRITES; i++ )//循环显示每一个精灵
{
if ( g_Sprite[i].iFangXiang == YUNDONG_UP ) //显示箭头的方向
{
prc.left=1; //在平面位图中的位置
prc.top=1;
prc.bottom = g_Sprite[i].dwHeight / 2;
prc.right = g_Sprite[i].dwWidth / 2;
}
else if( g_Sprite[i].iFangXiang == YUNDONG_DOWN )
{
prc.top = g_Sprite[i].dwHeight / 2 + 1;
prc.left = 1;
prc.bottom = g_Sprite[i].dwHeight;
prc.right = g_Sprite[i].dwWidth / 2;
}
else if( g_Sprite[i].iFangXiang == YUNDONG_RIGHT )
{
prc.top = 1;
prc.left = g_Sprite[i].dwWidth / 2 + 1;
prc.bottom = g_Sprite[i].dwHeight / 2;
prc.right = g_Sprite[i].dwWidth;
}
else if( g_Sprite[i].iFangXiang == YUNDONG_LEFT )
{
prc.top = g_Sprite[i].dwHeight / 2 + 1;
prc.left = g_Sprite[i].dwWidth / 2 + 1;
prc.bottom = g_Sprite[i].dwHeight;
prc.right = g_Sprite[i].dwWidth;
}
g_pDisplay->Blt( (DWORD)g_Sprite[i].fPosX, (DWORD)g_Sprite[i].fPosY, //显示精灵
g_pLogoSurface, &prc );
}
prc.top = 1;
prc.bottom = g_pTextSurface->GetHeight();
prc.left = 1;
prc.right = g_pTextSurface->GetWidth();
g_pDisplay->Blt( 10, 10, g_pTextSurface, NULL ); //在指定位置显示文字
if( FAILED(hr = g_pDisplay->Present() ) ) //呈现这一帧图像
return hr;
return S_OK;
}
//
// 更新表面 //
//
HRESULT RestoreSurfaces()
{
HRESULT hr;
if( FAILED( hr = g_pDisplay->GetDirectDraw()->RestoreAllSurfaces() ) ) //实例恢复所有表面
return hr;
if( FAILED( hr = g_pTextSurface->DrawText( NULL, "2935629", RGB( 0, 0, 0 ), RGB( 255, 255, 255 ) ) ) )
return hr;
if( FAILED( hr = g_pLogoSurface->DrawBitmap( MAKEINTRESOURCE( IDB_DIRECTX ) ) ) )
return hr;
return S_OK;
}
//
// 释放表面及实例 //
//
VOID FreeDirectDraw()
{
for( int i =0; i < NUM_SPRITES; i++ )
SAFE_DELETE( g_pLogoSurface );
SAFE_DELETE( g_pTextSurface );
SAFE_DELETE( g_pDisplay );
}
ddutil.h
//-----------------------------------------------------------------------------
// File: ddutil.cpp
//
// Desc: Routines for loading bitmap and palettes from resources
//
// Copyright (C) 1998-1999 Microsoft Corporation. All Rights Reserved.
//-----------------------------------------------------------------------------
#ifndef DDUTIL_H
#define DDUTIL_H
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } //释放对象的宏
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#include
//-----------------------------------------------------------------------------
// Classes defined in this header file
//-----------------------------------------------------------------------------
class CDisplay; //DirectX对象类
class CSurface; //平面对象类
//-----------------------------------------------------------------------------
// Name: class CDisplay
// Desc: Class to handle all DDraw aspects of a display, including creation of
// front and back buffers, creating offscreen surfaces and palettes,
// and blitting surface and displaying bitmaps.
//-----------------------------------------------------------------------------
class CDisplay
{
protected:
LPDIRECTDRAW7 m_pDD; //DirectX对象
LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; //DirectX对象的前平面对象
LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; //DirectX对象的后平面对象
HWND m_hWnd; //窗口的句柄
public:
CDisplay();
~CDisplay();
// 返回DirectX实例对应的DirectX对象
LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; }
//创建DirectX对象
HRESULT Create( HWND hWnd, DWORD dwWidth, DWORD dwHeight,
DWORD dwBPP );
virtual HRESULT DestroyObjects(); //释放DirectX对象
//创建位图平面
HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP,
DWORD dwDesiredWidth,
DWORD dwDesiredHeight );
//创建文字平面
HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont,
TCHAR* strText,
COLORREF crBackground,
COLORREF crForeground );
//清除屏幕
HRESULT Clear( DWORD dwColor = 0L );
//将表面对象显示在屏幕上
HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds,
RECT* prc, DWORD dwFlags=0 );
//将平面实例显示到屏幕上
HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc );
//显示缓存平面的内容(交换前后平面)
HRESULT Present();
};
//-----------------------------------------------------------------------------
// Name: class CSurface
// Desc: Class to handle aspects of a DirectDrawSurface.
//-----------------------------------------------------------------------------
class CSurface
{
LPDIRECTDRAWSURFACE7 m_pdds; //平面对象
DDSURFACEDESC2 m_ddsd; //平面结构
BOOL m_bColorKeyed; //是否使用透明颜色
DWORD dwWidth; //表面的有效宽度和高度
DWORD dwHeight;
public:
LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } //返回平面对象
BOOL IsColorKeyed() { return m_bColorKeyed; }//返回是否使用透明颜色
DWORD GetWidth() { return dwWidth; } //返回表面的有效宽度和高度
DWORD GetHeight() { return dwHeight; }
HRESULT DrawBitmap( HBITMAP hBMP ); //在表面画位图
HRESULT DrawBitmap( TCHAR* strBMP );
HRESULT DrawText( HFONT hFont, TCHAR* strText, //在平面设置文字
COLORREF crBackground, COLORREF crForeground );
HRESULT SetColorKey( COLORREF crColorKey ); //设置透明颜色
HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); //创建表面对象
CSurface();
~CSurface();
};
#endif // DDUTIL_H
ddutil.cpp
//-----------------------------------------------------------------------------
// File: ddutil.cpp
//
// Desc: DirectDraw framewark classes. Feel free to use this class as a
// starting point for adding extra functionality.
//
//
// Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#define STRICT
#include
#include
#include
#include
#include "ddutil.h"
//-----------------------------------------------------------------------------
// Name: CDisplay()
// Desc:
//-----------------------------------------------------------------------------
CDisplay::CDisplay()
{
m_pDD = NULL; //设置初值
m_pddsFrontBuffer = NULL;
m_pddsBackBuffer = NULL;
}
//-----------------------------------------------------------------------------
// Name: ~CDisplay()
// Desc:
//-----------------------------------------------------------------------------
CDisplay::~CDisplay()
{
DestroyObjects();
}
//-----------------------------------------------------------------------------
// Name: DestroyObjects()
// Desc: 释放已建立的对象
//-----------------------------------------------------------------------------
HRESULT CDisplay::DestroyObjects()
{
SAFE_RELEASE( m_pddsBackBuffer );
SAFE_RELEASE( m_pddsFrontBuffer );
if( m_pDD )
m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL );//取消与窗口的关联
SAFE_RELEASE( m_pDD );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CreateFullScreenDisplay()
// Desc: 创建DirectX对象
// 参数:窗口句柄,屏幕宽度,高度,深度
//-----------------------------------------------------------------------------
HRESULT CDisplay::Create( HWND hWnd, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP )
{
HRESULT hr;
// 释放已建立的对象
DestroyObjects();
// 创建DirectX对象(NULL,DirectX对象指针,DirectX对象类型,NULL)
if( FAILED( hr = DirectDrawCreateEx( NULL, (VOID**)&m_pDD,
IID_IDirectDraw7, NULL ) ) )
return E_FAIL;
// 设置关联的窗口(窗口句柄,方式
hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN );
if( FAILED(hr) )
return E_FAIL;
// 设置显示的模式(设置颜色时应与深度位数相对应)
if( FAILED( m_pDD->SetDisplayMode( dwWidth, dwHeight, dwBPP, 0, 0 ) ) )
return E_FAIL;
// 创建前平面结构
DDSURFACEDESC2 ddsd;
ZeroMemory( &ddsd, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd ); //设置结构长度
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; //有效选项
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | //方式
DDSCAPS_COMPLEX | DDSCAPS_3DDEVICE;
ddsd.dwBackBufferCount = 1; //后平面个数
//创建前平面(平面结构指针,前平面指针,NULL)
if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer,
NULL ) ) )
return E_FAIL;
// 设置平面信息结构
DDSCAPS2 ddscaps;
ZeroMemory( &ddscaps, sizeof( ddscaps ) );
ddscaps.dwCaps = DDSCAPS_BACKBUFFER; //设置为后平面
//创建后平面对象
if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps,
&m_pddsBackBuffer ) ) )
return E_FAIL;
m_pddsBackBuffer->AddRef(); //向系统申请加1
m_hWnd = hWnd; //保存场口句柄
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CDisplay::CreateSurfaceFromBitmap()
// Desc: Create a DirectDrawSurface from a bitmap resource or bitmap file.
// Use MAKEINTRESOURCE() to pass a constant into strBMP.
// Desc: 通过位图创建一个位图平面
// 参数:平面类指针,位图字符串,希望使用的宽度,希望使用的高度
//-----------------------------------------------------------------------------
HRESULT CDisplay::CreateSurfaceFromBitmap( CSurface** ppSurface,
TCHAR* strBMP,
DWORD dwDesiredWidth,
DWORD dwDesiredHeight )
{
HRESULT hr;
HBITMAP hBMP = NULL;
BITMAP bmp;
DDSURFACEDESC2 ddsd;
if( m_pDD == NULL || strBMP == NULL || ppSurface == NULL ) //判断创建条件
return E_INVALIDARG;
*ppSurface = NULL; //清除前面的内容
// 从资源中调用位图
hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP,
IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight,
LR_CREATEDIBSECTION );
if( hBMP == NULL )
{
//从文件中调用位图
hBMP = (HBITMAP) LoadImage( NULL, strBMP,
IMAGE_BITMAP, dwDesiredWidth, dwDesiredHeight,
LR_LOADFROMFILE | LR_CREATEDIBSECTION );
if( hBMP == NULL )
return E_FAIL;
}
//得到位图句柄
GetObject( hBMP, sizeof(bmp), &bmp );
// 从位图创建平面结构
ZeroMemory( &ddsd, sizeof(ddsd) );
ddsd.dwSize = sizeof(ddsd); //设置结构尺寸
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; //有效信息
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = bmp.bmWidth; //平面的宽度和高度(不能更改)
ddsd.dwHeight = bmp.bmHeight;
(*ppSurface) = new CSurface(); //创建新平面
if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) //通过结构创建平面
{
delete (*ppSurface);
return hr;
}
// 将位图画入平面
if( FAILED( hr = (*ppSurface)->DrawBitmap( hBMP ) ) )
{
DeleteObject( hBMP );
return hr;
}
DeleteObject( hBMP ); //删除位图指针
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CDisplay::CreateSurfaceFromText()
// Desc: Creates a DirectDrawSurface from a text string using hFont or the default
// GDI font if hFont is NULL.
// Desc: 通过文字创建一个文字平面
// 参数:平面类指针,字体,文字内容,背景颜色,前景颜色
//-----------------------------------------------------------------------------
HRESULT CDisplay::CreateSurfaceFromText( CSurface** ppSurface,
HFONT hFont, TCHAR* strText,
COLORREF crBackground, COLORREF crForeground )
{
HDC hDC = NULL;
LPDIRECTDRAWSURFACE7 pDDS = NULL;
HRESULT hr;
DDSURFACEDESC2 ddsd;
SIZE sizeText;
if( m_pDD == NULL || strText == NULL || ppSurface == NULL )//判断条件
return E_INVALIDARG;
*ppSurface = NULL;//清除前面的内容
hDC = GetDC( NULL ); //创建设备DC
if( hFont )
SelectObject( hDC, hFont ); //如果没有设置字体,则使用默认字体
GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); //得到显示文字的尺寸
ReleaseDC( NULL, hDC );
// Create a DirectDrawSurface for this bitmap
ZeroMemory( &ddsd, sizeof(ddsd) );
ddsd.dwSize = sizeof(ddsd); //设置结构尺寸
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;//有效信息
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = sizeText.cx;//平面的宽度和高度(不能更改)
ddsd.dwHeight = sizeText.cy;
(*ppSurface) = new CSurface();
if( FAILED( hr = (*ppSurface)->Create( m_pDD, &ddsd ) ) ) //通过结构创建平面
{
delete (*ppSurface);
return hr;
}
// 将文字写入平面
if( FAILED( hr = (*ppSurface)->DrawText( hFont, strText, crBackground, crForeground ) ) )
return hr;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: 交换前后平面
// 参数:
//-----------------------------------------------------------------------------
HRESULT CDisplay::Present()
{
HRESULT hr;
if( NULL == m_pddsFrontBuffer && NULL == m_pddsBackBuffer ) //判断条件
return E_POINTER;
while( 1 )
{
hr = m_pddsFrontBuffer->Flip( NULL, 0 ); //将前后平面交换,来显示刚刚画好的屏幕
if( hr == DDERR_SURFACELOST ) //平面丢失了
{
m_pddsFrontBuffer->Restore(); //恢复平面
m_pddsBackBuffer->Restore();
}
if( hr != DDERR_WASSTILLDRAWING )
return hr;
}
}
//-----------------------------------------------------------------------------
// Name: 将平面位图画到后平面上
// 参数: 后平面上的x坐标,后平面上的y坐标,平面对象,位图(文字)平面上的一个矩形区域,方式
//-----------------------------------------------------------------------------
HRESULT CDisplay::Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, RECT* prc,
DWORD dwFlags )
{
if( NULL == m_pddsBackBuffer )
return E_POINTER;
//将平面位图中的prc矩形区域画到后平面的x,y位置上
return m_pddsBackBuffer->BltFast( x, y, pdds, prc, dwFlags );
}
//-----------------------------------------------------------------------------
// Name: 将平面类对应的位图画到后平面上
// Desc: 后平面上的x坐标,后平面上的y坐标,平面类对象指针,位图(文字)平面上的一个矩形区域
//-----------------------------------------------------------------------------
HRESULT CDisplay::Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc )
{
if( NULL == pSurface )
return E_INVALIDARG;
if( pSurface->IsColorKeyed() ) //将平面实例上的位图画到后平面上
return Blt( x, y, pSurface->GetDDrawSurface(), prc, DDBLTFAST_SRCCOLORKEY );//清除透明色
else
return Blt( x, y, pSurface->GetDDrawSurface(), prc, 0L );//不清除透明色
}
//-----------------------------------------------------------------------------
// Name: 使用指定的颜色填充屏幕
// 参数: 颜色值
//-----------------------------------------------------------------------------
HRESULT CDisplay::Clear( DWORD dwColor )
{
if( NULL == m_pddsBackBuffer )
return E_POINTER;
// Erase the background
DDBLTFX ddbltfx;
ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillColor = dwColor; //定义颜色
//使用颜色填充平面
return m_pddsBackBuffer->Blt( NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
CSurface::CSurface()
{
m_pdds = NULL;
m_bColorKeyed = NULL; //只能为NULL,不能为FALSE
dwWidth = 0;
dwHeight = 0;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
CSurface::~CSurface()
{
SAFE_RELEASE( m_pdds );
}
//-----------------------------------------------------------------------------
// Name: 创建平面类的实例
// 参数:DirectX对象,平面的结构指针
//-----------------------------------------------------------------------------
HRESULT CSurface::Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd )
{
HRESULT hr;
// Create the DDraw surface创建一个平面
if( FAILED( hr = pDD->CreateSurface( pddsd, &m_pdds, NULL ) ) )
return hr;
// Use the passed size, unless zero
dwWidth = pddsd->dwWidth; //保留平面的尺寸
dwHeight = pddsd->dwHeight;
// Prepare the DDSURFACEDESC structure//定义平面实例对应的平面对象的结构
m_ddsd.dwSize = sizeof(m_ddsd);
// Get the DDSURFACEDESC structure for this surface//保存平面对象的结构
m_pdds->GetSurfaceDesc( &m_ddsd );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CSurface::DrawBitmap()向平面画一个位图
// 参数:位图的句柄
// Desc: Draws a bitmap over an entire DirectDrawSurface, stretching the
// bitmap if nessasary
// 注意:位图尺寸大于表面的尺寸时位图尺寸变小
//-----------------------------------------------------------------------------
HRESULT CSurface::DrawBitmap( HBITMAP hBMP )
{
HDC hDCImage;
HDC hDC;
BITMAP bmp;
DDSURFACEDESC2 ddsd;
HRESULT hr;
if( hBMP == NULL || m_pdds == NULL )
return E_INVALIDARG;
// Make sure this surface is restored.//平面刷新
if( FAILED( hr = m_pdds->Restore() ) )
return hr;
// Get the surface.description
ddsd.dwSize = sizeof(ddsd); //定义并得到表面的信息
m_pdds->GetSurfaceDesc( &ddsd );
if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC )//判断位图的格式
return E_NOTIMPL;
// Select bitmap into a memoryDC so we can use it.
hDCImage = CreateCompatibleDC( NULL ); //创建兼容设备
if( NULL == hDCImage )
return E_FAIL;
SelectObject( hDCImage, hBMP ); //设置为位图设备
// Get size of the bitmap
GetObject( hBMP, sizeof(bmp), &bmp );//得到位图的信息
// Stretch the bitmap to cover this surface
if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) //得到平面的DC
return hr;
StretchBlt( hDC, 0, 0, ddsd.dwWidth, ddsd.dwHeight, // 画到DC上
hDCImage, 0, 0, bmp.bmWidth, bmp.bmHeight,
SRCCOPY );
if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) )//释放
return hr;
DeleteDC( hDCImage );//释放
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CSurface::DrawText()
// Desc: Draws a text string on a DirectDraw surface using hFont or the default
// GDI font if hFont is NULL.
// 说明:将文字画到平面上
// 参数:字体,文字,背景色,字体色
//-----------------------------------------------------------------------------
HRESULT CSurface::DrawText( HFONT hFont, TCHAR* strText,
COLORREF crBackground, COLORREF crForeground )
{
HDC hDC = NULL;
HRESULT hr;
if( m_pdds == NULL || strText == NULL )
return E_INVALIDARG;
// Make sure this surface is restored.
if( FAILED( hr = m_pdds->Restore() ) ) //刷新表面
return hr;
if( FAILED( hr = m_pdds->GetDC( &hDC ) ) ) //得到DC
return hr;
// Set the background and foreground color
SetBkColor( hDC, crBackground ); //设置背景色
SetTextColor( hDC, crForeground ); //设置字体色
if( hFont )
SelectObject( hDC, hFont ); //设置字体
// Use GDI to draw the text on the surface
TextOut( hDC, 0, 0, strText, _tcslen(strText) ); //输出文字
SIZE sizeText;
GetTextExtentPoint32( hDC, strText, _tcslen(strText), &sizeText ); //得到显示文字的尺寸
dwHeight = sizeText.cx ; //保留字体的大小
dwHeight = sizeText.cy;
if( FAILED( hr = m_pdds->ReleaseDC( hDC ) ) )
return hr;
return S_OK;
}
//-------------------------------------------------
// Name: 向平面画一个位图
// 参数:位图的字符描述
//-------------------------------------------------
HRESULT CSurface::DrawBitmap( TCHAR* strBMP )
{
HBITMAP hBMP;
HRESULT hr;
if( m_pdds == NULL || strBMP == NULL )
return E_INVALIDARG;
//尝试从资源中加载位图,如果失败,尝试从一个文件中加载
// Try to load the bitmap as a resource, if that fails, try it as a file
hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL), strBMP,
IMAGE_BITMAP, 0, 0,
LR_CREATEDIBSECTION );
if( hBMP == NULL )
{
hBMP = (HBITMAP) LoadImage( NULL, strBMP, IMAGE_BITMAP,
0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION );
if( hBMP == NULL )
return E_FAIL;
}
// Draw the bitmap on this surface 在平面上画一个位图
if( FAILED( hr = DrawBitmap( hBMP ) ) )
{
DeleteObject( hBMP );
return hr;
}
DeleteObject( hBMP );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: 设置平面的透明颜色
// 参数: 透明颜色值
//-----------------------------------------------------------------------------
HRESULT CSurface::SetColorKey( COLORREF crColorKey )
{
if( NULL == m_pdds )
return E_POINTER;
m_bColorKeyed = TRUE; //使用透明颜色
DDCOLORKEY ddck;
ddck.dwColorSpaceLowValue = crColorKey;
ddck.dwColorSpaceHighValue = crColorKey;
return m_pdds->SetColorKey( DDCKEY_SRCBLT, &ddck );//设置透明颜色
}
资源文件
我的程序http://dl2.csdn.net/down4/20070629/29185221595.rar