这个事例程序是本人在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 <windows.h>
#include <mmsystem.h>
#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); //得到