你怎么还include cpp?
那个头文件是干啥的?
没法直接改你的代码
你看这个吧
#define INITGUID
#define
SafeRelease(x) if (x) { x->Release(); x=NULL; }
#define IMAGE_COUNT 6 //图片数目
?
char file_names[IMAGE_COUNT][256] = {??
?"E:/CJD/素材/pic/魔兽/1.bmp",
?"E:/CJD/素材/pic/魔兽/2.bmp",
?"E:/CJD/素材/pic/魔兽/3.bmp",
?"E:/CJD/素材/pic/魔兽/4.bmp",
?"E:/CJD/素材/pic/魔兽/5.bmp",
?"E:/CJD/素材/pic/魔兽/6.bmp"
};//图片列表
//函数声明
BOOL InitWindow(
HINSTANCE hInstance, int nCmdShow );
LRESULT
CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam );
int cur_image=0;//当前图片号
//变量说明
HWND hWnd; //窗口句柄
/*=============================================================================
LPDIRECTDRAW7和LPDIRECTDRAWSURFACE7类型(7是版本号)是在ddraw.h头文件里预定义的,
指向IDirectDraw7和IDirectDrawSurface7类型的长型指针(前面加的LP代表Long Point),
从后面用的是"->"而不是"."也可以看出这一点。
DD是DirectDraw的缩写,DDS是DirectDrawSurface的缩写,
因此习惯上我们把变量名起为lpDD和lpDDSXXX。
虽然VC.net自带的DirectX SDK是8.1版的,
但是由于Microsoft从DirectX
8.0起停止了对DirectDraw的更新,
所以DirectDraw目前的最新版本还是7.0。
===============================================================================*/
LPDIRECTDRAW7 lpDD=NULL;// DirectDraw对象的指针
LPDIRECTDRAWSURFACE7 lpDDSPrimary=NULL;// DirectDraw主页面的指针
LPDIRECTDRAWSURFACE7 lpDDSBuffer=NULL;// DirectDraw后台缓存页面的指针
LPDIRECTDRAWSURFACE7 lpSlides[IMAGE_COUNT];//图片存储空间
RECT rect;
?
void MakeRect
(int left, int top, int right, int bottom)
{
?rect.bottom = bottom;
?rect.left = left;
?rect.right = right;
?rect.top = top;
}
LPDIRECTDRAWSURFACE7 bitmap_surface(LPCTSTR
file_name)
{
?HDC hdc;
?HBITMAP bit;
?LPDIRECTDRAWSURFACE7 surf;
?//载入BMP
?bit=(HBITMAP) LoadImage(NULL,file_name,IMAGE_BITMAP,0,0,
??LR_DEFAULTSIZE|LR_LOADFROMFILE);
?if (!bit)//载入失败,返回NULL
??return NULL;
?//获得BMP尺寸
?BITMAP bitmap;
?GetObject(bit, sizeof(BITMAP), &bitmap );
?//保存BMP尺寸
?int surf_width = bitmap.bmWidth;
?int surf_height = bitmap.bmHeight;
?//创建页面
?HRESULT ddrval;
?DDSURFACEDESC2 ddsd;
?//清空DDSURFACEDESC2结构
?ZeroMemory(&ddsd,sizeof(ddsd));
?ddsd.dwSize = sizeof(DDSURFACEDESC2);
?//设置填充标示
?ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
?//离屏页面
?ddsd.ddsCaps.dwCaps =
DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
?//指定宽高
?ddsd.dwWidth =1024;
?ddsd.dwHeight =768;
?//创建离屏页面
?ddrval=lpDD->CreateSurface(&ddsd,&surf,NULL);
?if
(ddrval!=DD_OK) {
??//失败的话,释放BMP
??DeleteObject(bit);
??return NULL;
?}
?else //创建成功
?{
??//取得DC
??surf->GetDC(&hdc);
??//与DC取得一致
??HDC
bit_dc=CreateCompatibleDC(hdc);
??//
??SelectObject(bit_dc,bit);
??//传送bmp
??BitBlt(hdc,0,0,surf_width,surf_height,bit_dc,0,0,SRCCOPY);
??//释放DC
??surf->ReleaseDC(hdc);
??DeleteDC(bit_dc);
?}
?//释放BMP
?DeleteObject(bit);
?//返回离屏页面指针
?return surf;
}
//------ Function to Draw a
Slide ------//
void draw_slide()
{
?//确定我们取得了图片
?if (!lpSlides[cur_image]) {
??lpSlides[cur_image]=bitmap_surface(file_names[cur_image]);
??if (!lpSlides[cur_image])
???return;
?}
?//开始在屏幕上画
?//DrawImage();
?MakeRect
(0,0,1024,768);//设定传送rect
?//传送图像
?/*
Bltfast()就可以了。它的原形是:
?HRESULT BltFast(
?DWORD dwX,
?DWORD dwY,//图像将被传送到目标页面何处。
?LPDIRECTDRAWSURFACE
lpDDSrcSurface,//LPDIRECTDRAWSURFACE lpDDSrcSurface,//
?LPRECT lpSrcRect,//一个 RECT (Rectangle,即矩形)结构的地址,指明源页面上将被传送的区域。
???????????????????? //如果该参数是 NULL, 整个源页面将被使用。
?DWORD dwTrans??? //指定传送类型。有如下几种:
?????????????????
//DDBLTFAST_NOCOLORKEY
????? //指定进行一次普通的复制,不带透明成分。
????? //DDBLTFAST_SRCCOLORKEY?
?????
//指定进行一次带透明色的图像传送,使用源页面的透明色。
????? //DDBLTFAST_WAIT?
????? //如果图像传送器正忙,不断重试直到图像传送器准备好并传送好时才返回。
?????
//一般都使用这个参数。
?);
?*/
?lpDDSBuffer->BltFast(0,0,lpSlides[cur_image],&rect,DDBLTFAST_WAIT);
?/*
?? 注意到了没有?在这个例子中,我们将有3个页面,
??
就是主页面,用来换页的后台缓存页面以及用来存放图片的离屏页面
?? 创建完主页面和后台缓存页面,双缓存就很容易实现了,
?? 主要的差别就是图像要传送到后台缓存页面中进行而不是在主页面,
??
当一桢完成后,主页面调用Flip命令即可。
?????
Flip命令引起主页面与后台缓存页面的交换,但是这个动作不是马上进行,
?? 而是等到下次刷新周期的空白期才发生:)
?? Flip函数原型如下:
?? HRESULT Flip(
??
LPDIRECTDRAWSURFACE lpDDSurface,
???????? //换页链中另一个页面的
IDirectDrawSurface7接口的地址,
????????
//代表换页操作的目标页面。这个页面必须是换页链中的一员。
???????? //该参数缺省值是 NULL,
在这种情况下,
???????? //DirectDraw 从换页链中按照前后隶属关系依次换页。
?? DWORD
dwFlags//换页的标志选项,常用DDFLIP_WAIT,同BltFast中的DDBLTFAST_WAIT差不多。
??
);
????? 一般我们这样即可换页:
??
lpDDSPrimary->Flip(NULL,DDFLIP_WAIT);
?*/
?lpDDSPrimary->Flip(NULL,DDFLIP_WAIT);//换页
?//
换图片,准备画下一张,并判断图片索引,形成循环
?int
next_slide=(cur_image>=IMAGE_COUNT-1) ? 0 : cur_image+1;
?if (!lpSlides[next_slide])
??lpSlides[next_slide]=bitmap_surface(file_names[next_slide]);
?int prev_slide=(cur_image<1) ? IMAGE_COUNT-1 :
cur_image-1;
?if (!lpSlides[prev_slide])
??lpSlides[prev_slide]=bitmap_surface(file_names[prev_slide]);
}
Top
//************************************************************
//函数:InitDDraw()
//功能:DX初始化函数
//************************************************************
BOOL InitDDraw()
{
?DDSURFACEDESC2 ddsd; //
DirectDraw的页面描述
? /*
??? 在一切工作之前,记得加入两个lib文件
??? 在菜单Project-Setting下的Link页的Object/Library Modules栏里加入
??? "ddraw.lib"和"dxguid.lib" ,后者可以不加入,而用#define INITGUID代替
??? PS:最好选择setting for All Configurations
???
这样会在 debug 和 release 下都有效
? */
? /*
??? 如果要使用DirectDraw,必须创建一个DirectDraw对象,它是DirectDraw接口的核心。
??? 用DirectDrawCreateEx( )函数可以创建DirectDraw对象,
???
DirectDrawCreateEx( )函数是在ddraw.h中定义的,它的原型如下:
??????
HRESULT WINAPI DirectDrawCreateEx(
? ?????? GUID
FAR *lpGUID, //指向DirectDraw接口的GUID的指针,NULL表示采用默认(当前)
?
?????? LPVOID *lplpDD,?? //用来接受初始化的DirectDraw对象的地址
?
?????? REFIID iid,?????? //IID_IDirectDraw7,当前版本
?
?????? IUnknown FAR *pUnkOuter? //NULL? 保留
??? );
?????? 所有的DirectDraw函数的返回值都是HRESULT类型,它是一个32位的值。
??? 函数调用成功用 "DD_OK"表示,
??? 所有的错误值标志开头都为"DDERR",如:
??? DDERR_DIRECTDRAWALREADYCREATED
??? DDERR_OUTOFMEMORY
? */
? //这里使用了 if (xxx!=DD_OK)
的方法进行错误检测,这是最常用的方法
???? if
(DirectDrawCreateEx(NULL,(LPVOID*)&lpDD, IID_IDirectDraw7,
NULL)!= DD_OK)
??return FALSE; //创建DirectDraw对象
?
/*
? DirectDrawCreate函数调用成功后,lpDD已经指向了一个DirectDraw对象,
? 它是整个DirectDraw接口的最高层领导,以后的步骤都是在它的控制之下。
?
我们用IDirectDraw7::SetCooperativeLevel( )来设置DirectDraw程序对系统的控制级。
? 它的原型如下:
? HRESULT SetCooperativeLevel (HWND hWnd,
DWORD dwFlags )
?
第一个参数是窗口句柄,我们给它hWnd,使DirectDraw对象与主窗口联系上。
????
第二个参数是控制级标志。这里使用DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN,
?
表示我们期望DirectDraw以独占和全屏方式工作。
????
?
控制级描述了DirectDraw是怎样与显示设备及系统作用的。
?
DirectDraw控制级一般被用来决定应用程序是运行于全屏模式(必须与独占模式同时使用),
?
还是运行于窗口模式。但DirectDraw的控制级还可设置如下两项:
????
(1)允许按Ctrl+Alt+Del重新启动(仅用于独占模式,为DDSCL_ALLOWREBOOT)。
????
(2)不允许对DirectDraw应用程序最小化或还原 (DDSCL_NOWINDOWCHANGES)。
????
? 普通的控制级(DDSCL_NORMAL)表明我们的DirectDraw应用程序将以窗口的形式运行。
?
在这种控制级下,我们将不能改变显示器分辨率,或进行换页操作(这是一个重要的操作)。
?
除此之外,我们也不能够调用那些会对显存产生激烈反应的函数,如Lock()。
????
当应用程序为全屏并且独占的控制级时,我们就可以充分的利用硬件资源了。
?
此时其它应用程序仍可创建页面、使用DirectDraw或GDI的函数,只是无法改变显示模式。
? */
???? if
(lpDD->SetCooperativeLevel(hWnd,DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE|
?? DDSCL_ALLOWREBOOT)!= DD_OK)
??????? return
FALSE; //设置DirectDraw控制级
? /*
?
下一步我们使用IDirectDraw7::SetDisplayMode( )来设置显示模式,其原形为:
?
HRESULT SetDisplayMode(
? DWORD dwWidth,
?
DWORD dwHeight, //dwWidth and dwHeight用来设置显示模式的宽度和高度。
?
DWORD dwBPP, //dwBPP用来设置显示模式的颜色位数。
? DWORD
dwRefreshRate, //dwRefreshRate设置屏幕的刷新率,0为使用默认值。
? DWORD
dwFlags //dwFlags现在唯一有效的值是DDSDM_STANDARDVGAMODE,
??????????????? //此值是如果在320×240×8模式下给VGA Mode 13用的,
?????? //我们通常把它设为0即可
?????
? );
?
PS:用IDirectDraw7接口的EnumDisplayModes()函数
????
可以取得当前可用的模式列表。具体用法请查阅DX的帮助
? */
???? if
(lpDD->SetDisplayMode(1024,768,32,85,0)!= DD_OK)
??????? return FALSE; //设置显示模式
??? /*
?? 创建一个页面之前,首先需要填充一个DDSURFACEDESC2结构,
?? 它是DirectDraw
Surface Description的缩写,意思是DirectDraw的页面描述。
??
它的结构非常庞大,这里只能作一个最简单的介绍。
?? 要注意的是在填充此结构前一定要将其清空!
?*/
?//开始创建主页面,先清空页面描述
?ZeroMemory(&ddsd,
sizeof(ddsd));
?//填充页面描述
??? ddsd.dwSize
= sizeof(ddsd);//给dwSize页面描述的大小
?ddsd.dwFlags =
DDSD_CAPS|DDSD_BACKBUFFERCOUNT;//有后台缓存
???
ddsd.ddsCaps.dwCaps =DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|
??DDSCAPS_COMPLEX;//主页面,有后台缓存,有换页链
?ddsd.dwBackBufferCount =
1;//后台缓存数为1
??? /*
?CreateSurface(
)函数的第一个参数是被填充了页面信息的DDSURFACEDESC2结构的地址,
?此处为&ddsd;
?第二个参数是接收主页面指针的地址,此处为&lpDDSPrimary;
?第三个参数现在必须为NULL,为该函数所保留。
???
如果函数调用成功,lpDDSPrimary将成为一个合法的主页面对象。
?由于在前面已经设置了该程序的工作模式为独占和全屏,
?所以,此时主页面所代表的实际上是我们的整个显示屏幕。
?在主页面上所绘制的图形将立即反映到我们的显示屏幕上。
?*/
???? if
(lpDD->CreateSurface(&ddsd,&lpDDSPrimary, NULL) !=
DD_OK )
????? ?return FALSE; //创建主页面
??? ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; //后台缓存页面
??? /*
?在创建主页面的时候,附加页面(这里是后台缓存页面)也同时创建了,
?但是他们没有被你调用的CreateSurface()所返回
?你要通过GetAttachedSurface()函数来取得该接口,
?*/
??? if
(lpDDSPrimary->GetAttachedSurface(&ddsd.ddsCaps,&lpDDSBuffer)!=DD_OK)
??return FALSE; //创建后台缓存页面
?lpSlides[0]=bitmap_surface(file_names[0]);
?if
(!lpSlides[0])
??return FALSE;
?//画图
?draw_slide();
?return TRUE;
}
void Cleanup(void)
{
?//释放接口
?for
(int i=0;i??SafeRelease(lpSlides[i]);
?SafeRelease(lpDDSBuffer);
?SafeRelease(lpDDSPrimary);//删除主页面
?SafeRelease(lpDD);//删除ddraw对象
?//ps:与创建的顺序正好相反
}
//************************************************************
//函数:WinMain()
//功能:Windows程序入口函数。创建主窗口,处理消息循环
//************************************************************
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE
hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
? if ( !InitWindow(hInstance, nCmdShow ) ) return
FALSE; //创建主窗口
? //如果创建不成功则返回FALSE并同时退出程序
? MSG
msg;
? //进入消息循环:
? for(;;)
? {
?if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
?{
??if ( msg.message==WM_QUIT) break;
??TranslateMessage(&msg);
??DispatchMessage(&msg);
?}
? }
?? return msg.wParam;
}
Top