写DIRECTDRAW中的第一个例子
来源:互联网 发布:淘宝男士长款钱包 编辑:程序博客网 时间:2024/06/10 01:22
呵呵,今天早上一起来就听到老婆的手机不行了,唉。我也想换一个,怎么舍不得咯。
不管了,我今天要学DirectDraw了。一定要在一周之内做完。
首先用的第一个例子是directdraw.chm 里面的一个DirectDraw入门程序
- 选择Link栏,在Object/Library modules中添入“Ddraw.lib”。
- 请注意:这一步骤是将DirectDraw的静态连接库文件连接到工程中,否则,程序虽然可以正常编译,但是在连接时会产生一个“unresolved external symbol”(没有定义的外部符号)的错误。在以后所有的DirectDraw程序中,都必须将与你所用到的DirectDraw组件相应的静态连接库添入到这个设置中。
我按照文档提示的来,并没有出现文档所提示的效果。有点郁闷,我只能往下看了。我昨天也调试了很久,没有调出来。我开始以为是TEXTOUT这个函数显示字符串的问题,但现在看来,又好像不是,我迷惑了。
函数调用顺序依次是这样的。
WinMain ----> InitWindow ----> InitDDraw ----> WinProc ----> FreeDDraw
WinMain:所有Win32应用程序的入口函数,它也是应用程序关闭时的出口,一个应用程序的全生命周期就是在它的控制之下。所以,确切的说,其它四个函数是被包括在WinMain之内的。消息循环也是在这个函数中启动。
InitWindow:初始化和创建一个与程序的HINSTANCE(实例句柄)相关联的主窗口,这个窗口的HWND(窗口句柄)在初始化DirectDraw环境时需要用到。
InitDDraw:初始化和创建DirectDraw对象,并执行一定的功能。它里面包括了创建DirectDraw对象,创建页面,设置显示模式,创建主页面,输出文字。
WinProc:是应用程序感知外来动作和产生反应的神经中枢,相当于人的大脑。这是程序中最主要的部件之一,它和在WinMain中所启动的消息循环是一起工作的。
FreeDDraw:释放DirectDraw的各种对象,以使其不再占用内存空间。
第一个是DirectDraw对象,表示显示硬件,它包括了显示器和显卡还有显存,用它来代表整个显示系统。
第二个是DirectDrawSurface对象,表示页面,你可以在大脑中把它想象成一张矩形的白纸,你可以在上面绘制图象。
这里所说的“对象”(Object),并不完全等同于C++中对象的概念,尽管它们使用的是同一个英文单词Object。这里的对象指的是COM,COM是Component Object Model 的缩写,代表“部件对象模型”,它在DirectX中贯穿始终,无处不是它的身影
HRESULT DirectDrawCreate(GUID FAR * lpGUID, LPDIRECTDRAW FAR * lplpDD, IUnknown FAR * pUnkOuter); ---àThis function creates an instance of a DirectDraw object.
第一个参数是lpGUID:指向DirectDraw接口的全局唯一标志符(GUID:Global unique identify)的指针。在这里,我们给它NULL,表示我们将使用当前的DirectDraw接口。
第二个参数是lplpDD:这个参数是用来接受初始化成功的DirectDraw对象的地址。在这里,我们给它&lpdd。
第三个参数是pUnkOuter:千万不要追问这个参数是干嘛使的,如果你不想惹麻烦,就给它NULL吧。Microsoft的说明书上是这么写的“考虑到与将来的COM集合特性保持兼容,当前,不管怎样,如果这个参数不是NULL ,DirectDrawCreate将返回一个错误”。
所有的DirectDraw函数的返回值都是HRESULT类型,它是一个4字节(32位)的值,用来代表某个错误或警告。DirectDraw头文件中已经预定义了所有可能的返回值常量,仅函数返回成功的值是用 “DD_OK”表示,所有的错误值标志开头都为“DDERR”,如:
DDERR_DIRECTDRAWALREADYCREATED
DDERR_GENERIC
DDERR_OUTOFMEMORY
这个语句用来设置应用程序对操作系统的控制程度。它的原型如下:
HRESULT SetCooperativeLevel( HWND hWnd, DWORD dwFlags )
IDirectDraw4::SetCooperativeLevel
The IDirectDraw4::SetCooperativeLevel method determines the top-level behavior of the application. 这个函数在MSDN2001里才有,2005里面已经找不到这个函数了。
第一个参数是hWnd,我们调用Win32的API函数GetActiveWindow获得应用程序主窗口的句柄,这将使DirectDraw对象与主窗口的消息挂上勾。
第二个参数是dwFlags,控制级的标志符。我们给它DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,表示我们期望DirectDraw以独占和全屏方式工作。
这个函数有很多用法,而且它必须在创建DirectDraw对象之后,立即调用。你可以用它来设置应用程序是运行于全屏还是窗口模式,是独占还是共享模式。
问题,怎么才能不让它全屏显示 了。我感觉应该会有一个这样的函数。
if ( lpDD->SetDisplayMode( 640, 480, 8 ) != DD_OK) return FALSE;
显而易见,这是设置显示器的显示模式,它把显示模式设为640*480,8位色彩模式(即256色)。这是绝大多数显示器所能够支持的显示模式,所以我们不用担心它会出什么问题。在以后的例程中,我们将看到可以调用EnumDisplayModes()来列举出显示器所支持的所有显示模式。绝不要轻易尝试直接设置一个新的显示模式,而应从列举出的显示模式中选择,这也将在后续章节讲到。
· 要注意的是,只有当DirectDraw对象为独占访问的控制程度时才能改变显示器的显示模式,如果DirectDraw对象运行为窗口模式,调用该函数会返回一个错误。
4)创建主页面
然后的任务是要创建一个DirectDrawSurface对象。
DirectDrawSurface对象代表了一个页面。页面可以有很多种表现形式,它既可以是可见的(屏幕的一部分或全部),称之为主页面(Primary Surface);也可以是作换页用的不可见页面,称之后台缓存(Back Buffer),在换页后,它成为可见;还有一种始终不可见的,称之为离屏页面(Off-screen Surface),用它来存储图象。其中,最重要的页面是主页面,每个DirectDraw应用程序都必须创建至少一个主页面,用它来代表屏幕上可见的区域,说白了,就是你的显示屏幕。
创建一个页面要分两步走,这里,我们以创建主页面为例
- 在调用CreateSurface()函数创建一个页面之前,首先需要填充一个DDSURFACEDESC的结构,它是DirectDraw Surface Description的缩写,意思是DirectDraw的页面描述。该结构的详细资料请参MSDN。
//填充主页面信息
ddsd.dwSize = sizeof( ddsd ); //结构的大小
ddsd.dwFlags = DDSD_CAPS; //指定DDSURFACEDESC结构的ddsCaps成员为可用
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; //指定要创建的是主页面
- 这就象是你到银行取款,必须事先填写一张取款单,你要在上面详细描述你的姓名,你的存折序号,以及你要取的钱数等等,然后把它递给银行工作人员。
- 页面描述填充完毕后,把它传递给CreateSurface()函数即可。
//创建主页面对象
if ( lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ) != DD_OK)
return FALSE;
CreateSurface()函数的第一个参数是被填充了页面信息的DDSURFACEDESC结构的地址,为&ddsd;第二个参数是接收主页面指针的地址,此处为&lpDDSPrimary;第三个参数现在必须为NULL,为该函数所保留。
如果函数调用成功,lpDDSPrimary将代表一个合法的主页面对象。由于在前面已经设置了该程序的工作模式为独占和全屏,所以,此时主页面所代表的实际上是你的整个显示屏幕。在主页面上所绘制的图形将立即反映到你的显示屏幕上。
5)输出文字
下面开始在主页面上输出文字。
//输出文字
if ( lpDDSPrimary->GetDC(&hdc) != DD_OK) return FALSE; //获得设备环境句柄
SetBkColor( hdc, RGB( 0, 0, 255 ) ); //设置背景颜色
SetTextColor( hdc, RGB( 255, 255, 0 ) ); //设置文字颜色
TextOut( hdc, 220, 200, szMsg1, lstrlen(szMsg1)); //输出文字
TextOut( hdc, 280, 240, szMsg2, lstrlen(szMsg2));
lpDDSPrimary->ReleaseDC(hdc); //释放资源
这里有一点点的小问题,这里和VC2005有区别。在注意了。TEXTOUT
通过本章的学习,读者应能掌握:
· 在VC++5.0环境中使用Win32应用程序开发环境新建一个DirectDraw工程以及添加源文件。
· 用DirectDrawCreate()函数创建DirectDraw对象,并立即调用SetCooperativeLevel()设置其控制级,注意其第一个参数为应用程序主窗口句柄。
· 只有在独占的控制级下才能调用SetDisplayMode()以改变显示器的显示模式。
· 在调用CreateSurface ()创建DirectDrawSurface对象之前,必须先填充一个DDSURFACEDESC结构以描述页面的信息。
· 页面对象的种类,只有主页面代表了显示屏幕,为可见页面。
· 用GetDC()获得主页面的HDC,然后可以使用Windows API的GDI函数进行绘图或输出文字,最后必须调用ReleaseDC()以释放资源。
· DirectDraw接口的对象必须被及时的用Release()函数释放。
这里的代码看完了,我依然不知道为什么看不到代码所提示的现象,所以,我要看看例子程序了。我把整个例子程序的代码都复制到我的学习DirectDraw目录下面。DDraw
这里我看一下第一个例子。它也是在屏幕上面输出文字。
睡了一觉醒来,还是不知道哪里错了。
IDirectDrawSurface3::Flip
该函数完成一次换页操作。将与后台缓冲区相关联的页面内存换页成与前台缓冲区页面相关联。
HRESULT Flip(
LPDIRECTDRAWSURFACE3 lpDDSurfaceTargetOverride,
DWORD dwFlags
);
lpDDSurfaceTargetOverride -- >The default for this parameter is NULL, in which case DirectDraw cycles through the buffers in the order that they are attached to each other. 该参数缺省值是NULL,在这种情况下,DirectDraw从换页链中按照前后隶属关系依次换页。
DDERR_SURFACELOST
Access to the surface is refused because the surface memory is gone. Call the IDirectDrawSurface7::Restore method on this surface to restore the memory associated with it.
DDERR_WASSTILLDRAWING
The previous blit operation that is transferring information to or from this surface is incomplete.
IDirectDrawSurface7::Restore
The IDirectDrawSurface7::Restore method restores a surface that has been lost. This occurs when the surface memory associated with the DirectDrawSurface object has been freed. 恢复丢失的页面。与DirectDrawSurface对象相关联的页面内存被释放时,会导致页面丢失
经过一天的折腾,我决定把今天看到的代码自己写一遍,加深印象。
1:新建一个基于WIN32的应用程序,我这里加的不是CONSOLE应用程序,要注意拉。
2:
//*******************************************************************
//包含头文件
//*******************************************************************
#include <windows.h>
#include <ddraw.h>
#include <stdio.h>
#include <stdarg.h> //定义成一个可变参数列表的指针
#include "resource.h"
3: //*******************************************************************
//函数:WinMain()
//功能:Win32应用程序入口函数。进行初始化工作,处理消息循环
//*******************************************************************
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nShowCmd //这里跟示例中的不一样,int PASCAL WinMain
)
{
MSG msg;
////初始化主窗口
if (InitApp(hInstance, nCmdShow) != DD_OK)
return FALSE;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
4://******************************************************************
//函数:InitApp(HINSTANCE hInstance, int nCmdShow)
//功能:创建主窗口。初始化DirectDraw环境并实现其功能。包括:创建DirectDraw对象,
// 设置显示模式,创建主页面。
//******************************************************************/
static HRESULT
InitApp(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
WNDCLASS wc; //初始化窗口用
DDSURFACEDESC2 ddsd; //The DDSURFACEDESC2 structure contains a description of a surface
DDSCAPS2 ddscaps;
HRESULT hRet; //初始化DirectDraw环境
// Set up and register window class
wc.style = CS_HREDRAW | CS_VREDRAW; //窗口重绘时,水平垂直重画
wc.lpfnWndProc = WindowProc; //WindowProc是一个函数指针,指向窗口过程函数
wc.cbClsExtra = 0; //类附加内存,默认为
wc.cbWndExtra = 0; //窗口附加内存,默认为
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN_ICON));
//MAKEINTRESOURCE宏把资源ID标识符转换为需要的LPCTSTR类型
/*HICON LoadIcon(
HINSTANCE hInstance,
LPCTSTR lpIconName
);
*/
wc.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));//这里的这个宏是我自己加的
wc.hbrBackground = (HBRUSH )GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NAME;
wc.lpszClassName = NAME;
RegisterClass(&wc);
// Create a window
hWnd = CreateWindowEx(WS_EX_TOPMOST,
//WS_EX_TOPMOS 的含义Specifies that a window created with this style should be placed above all
//non-topmost windows and should stay above them
NAME,
TITLE,
WS_POPUP,//窗口的类型用的是WS_POPUP,表明创建的是一个没有标题栏,没有边框的窗口;
//而不是常用的WS_OVERLAPPEDWINDOW
0,
0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL,
NULL,
hInstance,
NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
SetFocus(hWnd); //功能设置键盘焦点到指定的窗口
///////////////////////////////////////////////////////////////////////////
// Create the main DirectDraw object
///////////////////////////////////////////////////////////////////////////
hRet = DirectDrawCreateEx(NULL, (VOID**)&g_pDD, IID_IDirectDraw7, NULL);
//第二个参数是用来接受初始化成功的DirectDraw对象的地址
//第三个参数This parameter must be set to IID_IDirectDraw7
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "DirectDrawCreateEx FAILED");
// Get exclusive mode
hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "SetCooperativeLevel FAILED");
// Set the video mode to 640x480x8
hRet = g_pDD->SetDisplayMode(640, 480, 8, 0, 0);
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "SetDisplayMode FAILED");
// Create the primary surface with 1 back buffer
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
//The dwBackBufferCount and ddsCaps member is valid.
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX;
//DDSCAPS2 structure that contains the capabilities of the surface.
//DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DSCAPS_COMPLEX; 要查看MSDN
ddsd.dwBackBufferCount = 1;//Number of back buffers.
hRet = g_pDD->CreateSurface(&ddsd, &g_pDDSPrimary, NULL);
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "CreateSurface FAILED");
// Get a pointer to the back buffer
ZeroMemory(&ddscaps, sizeof(ddscaps));
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
hRet = g_pDDSPrimary->GetAttachedSurface(&ddscaps, &g_pDDSBack);
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "GetAttachedSurface FAILED");
// Create a timer to flip the pages
if (TIMER_ID != SetTimer(hWnd, TIMER_ID, TIMER_RATE, NULL))
return InitFail(hWnd, hRet, "SetTimer FAILED");
return DD_OK;
}
因为中间有很调用的函数和变量,所以要在程序中定义。
/*******************************************************************
//局部定义
//*******************************************************************
#define NAME "DDExample1"
#define TITLE "Direct Draw Example 1"
//*******************************************************************
//全局变量
//*******************************************************************
LPDIRECTDRAW7 g_pDD = NULL; // DirectDraw object
LPDIRECTDRAWSURFACE7 g_pDDSPrimary = NULL;// DirectDraw primary surface
LPDIRECTDRAWSURFACE7 g_pDDSBack = NULL; // DirectDraw back surface
BOOL g_bActive = FALSE; // Is application active?
//*******************************************************************
// 默认设置
//*******************************************************************
#define TIMER_ID 1
#define TIMER_RATE 500
函数部分
//******************************************************************/
// Name: InitFail()
// Desc: This function is called if an initialization function fails
//这个函数在我所学的代码里面没有。但在Win32应用程序入口函数里有代码实现了这个功能。
/*if ( !InitDDraw())
{
MessageBox(GetActiveWindow(),L"初始化DirectDraw过程中出错!",L"Error", MB_OK );
FreeDDraw();
DestroyWindow(GetActiveWindow());
return FALSE;
}*/
//******************************************************************/
HRESULT
InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...)
{
char szBuff[128];
va_list vl;
va_start(vl, szError); //va在这里是variable-argument(可变参数)的意思.
vsprintf(szBuff, szError, vl);
ReleaseAllObjects();
MessageBox(hWnd, szBuff, TITLE, MB_OK);
DestroyWindow(hWnd);
va_end(vl);
return hRet;
}
//这里的关于可变参数的问题我没有深入。好烦的。
//******************************************************************/
// Name: ReleaseAllObjects()
// Desc: Finished with all objects we use; release them
// 这里的代码跟我所学的代码差不多,只是符号有所变化。
//******************************************************************/
static void
ReleaseAllObjects(void)
{
if (g_pDD != NULL) //g_pDD is DirectDraw object
{
if (g_pDDSPrimary != NULL) //g_pDDSPrimary is DirectDraw primary surface
{
g_pDDSPrimary->Release();
g_pDDSPrimary = NULL;
}
g_pDD->Release();
g_pDD = NULL;
}
}
5:这里我就不接着写了,写几个关键的地方,
第一个就是函数的顺序的问题。
第二个要在Project->Configuration Properties->General->Character Set,选择“Use Unicode Character Set”就是使用Uncode字符集,选择” Use Multi-Byte Character Set”就是多字节字符集。
第三个Project->Configuration Properties->linker->additional dependenices ->dxguid.lib ddraw.lib 加入这两个库
第四个,注意修改int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine, //这个参数的类型要改一下
int nCmdShow ) //这个参数的名字要改一下
- 写DIRECTDRAW中的第一个例子
- 深入浅出Hibernate中的第一个例子
- 【Inter汇编语言程序设计】中的第一个例子
- 5、第一个例子
- opengl 第一个例子
- hibernate第一个例子
- ajax 第一个例子
- JavaBeans第一个例子
- SiteMesh第一个例子
- Mina第一个例子
- Hibernate---->第一个例子
- Servlet第一个例子
- struts2第一个例子
- struts2第一个例子
- zTree第一个例子
- AJAX 第一个例子
- Hibernate第一个例子
- Mybatis第一个例子
- oracle中复制一个用户
- Read a bit and take it out,the come back read some more
- layoutSubview 调用时机
- android webview点击返回键返回上一个html
- How to install a PHP PECL extension/module on Ubuntu
- 写DIRECTDRAW中的第一个例子
- Redhat:使用本地源或光盘镜像做yum源
- Android Audio代码分析26 - Audio Strategy
- mysql须知
- jQuery Ajax在IE8中的Cache问题
- How to use the PECL HTTP (PECL_HTTP) Extension to make HTTP requests from PHP
- http://news.csdn.net/a/20111020/306146.html
- HDOJ 2048 神、上帝以及老天爷(错排公式)
- 时序收敛地最佳实践