DDraw笔记-一个简单的DDraw应用程序

一个简单的DDraw应用程序 

方煜宽

2011.05.13

上次谈到DDraw是一个组件。组件由接口组成。

DDraw总共由五个接口组成: 

IUnknown:所有com接口都必须从这里继承的。(请看相关文章COM笔记-QueryInterface函数

IDirectDraw:使用DDraw必须创建的主接口对象。

IDirectDrawSurface:创建、控制和显示的实际显示表面。分主显示表面和从显示表面

IDirectDrawPalette:创建、加载和控制调色板,以及将它关联到显示表面。

IDirectDrawClipper:剪切DDraw光栅和位图操作到一些可见显示表面的子集。

 2011051323462934.png

 2011051323470780.png 

 2011051323473246.png

这些接口怎么配合起来成为一个DDraw应用程序的: 

1.  创建DDraw对象并使用QueryInterface()来得到 一个IDirectDraw7接口,或是直接用DirectDrawCreateEx()创建一个DDraw7接口。用这个接口来设置协作级别和视频模式。

2.  使用IDirectDrawSurface7接口至少创建 一个主显示表面用以绘图。(如果每个像素为8位或更少我们会用到一个调色板)

3.  用IDirectDrawPalette接口创建 一个调色板。(注意如果像素高于8位,如16位、24位,32位,没有调色板,现在主流2D游戏多数是16色)

4.  如果DDraw应用程序要使用窗口,或者要减少位图以免溢出DDraw显示表面的可见边界,我们至少需要合建一个剪裁器并将其尺寸设置为可见窗口的范围。如下图

 2011051323480635.png

5.  最后就是在表面上绘图了。

下面开始介绍一个最简单的DDraw应用程序: 

创建DDraw对象:

用来DirectDrawCreateEx来直接创建DDraw对象,声明如下:

  

 
  
HRESULT WINAPI DirectDrawCreateEx(
GUID FAR
* lpGUID, // 视频显卡驱动的GUID,NULL表示系统默认的硬件
LPVOID
* lplpDD, // 这是返回的接口
REFIID iid,
// 请求接口相对应的ID
IUnknown FAR
* pUnkOuter // 总是高为NULL
);

  

设置协作级别:

对DDraw来说,我们唯一关心的是视频显示设备,有两种情况:全屏模式和窗口模式。

用SetCooperativeLevel来设置DDraw的协作级别。声明如下:

 
  
HRESULT SetCooperativeLevel(HWND hWnd, // 窗口句柄,一般使用主窗口句柄
DWORD dwFlags);
// 控制标志

dwFlags控制标志,它直接影响DDraw与Windows之间协作方式。

SetCooperativeLevel()的控制标记 

描述

DDSCL_ALLOWMODEX

允许使用Mode X (320x200,240,400) 显示模式.公当设置DDSCL_EXCLUSIVE和DDSCL_FULLSCREEN时生效

DDSCL_ALLOWREBOOT

允许在排他(全屏)模式下检测到Ctrl+Alt+Del

DDSCL_EXCLUSIVE

请求排他级别。此标记需要与DDSCL_FULLSCREEN标记同时作用

DDSCL_FPUSETUP

表示调用 程序希望配置FPU以得到最佳的Direct3D性能(禁用度和异常),这样Direct3D不需要每次都明确地FPU。更多信息,请在DirectX SDK中查询“DDraw协作级别和FPU数度”

DDSCL_FULLSCREEN

表示使用全屏模式。其他应用程序的GDI将不能写屏,此标记必须与DDSCL_EXCLUSIVE标记同时使用。

DDSCL_MULTITHREADED

请求对于多线程安全的DDraw行为。

DDSCL_NORMAL

表示应用程序是一个通常的Windows应用程序。这个标记不能与DDSCL_ALLOWMODEX, DDSCL_EXCLUSIVE, 或 DDSCL_FULLSCREEN标记一起使用。

DDSCL_NOWINDOWCHANGES

表示不允许DDraw激活时最小化或还原应用程序窗口。

上面写了一大堆标记,其实大多数情况是下面两种情况。

全屏模式:DDSCL_FPUSETUP | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT

窗口模式:DDSCL_NORMAL

下面例子:

因为是用于学习,没有把框架搞得太复杂,全写在一个cpp里了。

关于怎么写一个GUI应用程序,可以查看《一个简单的windows GUI应用程序

http://www.cnblogs.com/fangyukuan/archive/2010/08/31/1814159.html

源代码下载

 
  
// -------------------------------------------------------------------------
// 文件名 : 6_1.cpp
// 创建者 : 方煜宽
// 邮箱 : fangyukuan@gmail.com
// 创建时间 : 2010-12-1 23:37
// 功能描述 : 一个简单的DDraw应用程序
// 注意在工程中把ddraw.lib包含进去
// -------------------------------------------------------------------------
#define INITGUID

#include
< windows.h >
#include
< ddraw.h >

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HWND main_window_handle
= NULL; // 主窗口句柄
LPDIRECTDRAW7 lpdd
= NULL;    // DDraw 对象

int Game_Init( void * parms = NULL, int num_parms = 0 )
{
// 创建ddraw对象
if (FAILED(DirectDrawCreateEx(NULL, ( void ** ) & lpdd, IID_IDirectDraw7, NULL)))
return ( 0 );

// 窗口模式(设置协作级别)
lpdd
-> SetCooperativeLevel(main_window_handle, DDSCL_NORMAL);
return 1 ;
}

/
int Game_Shutdown()
{
if (lpdd)
{
lpdd
-> Release();
lpdd
= NULL;
}
return 1 ;
}

int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
HWND hwnd;
MSG msg;
TCHAR lpszClassName[]
= TEXT( " kuan " );

WNDCLASS wc;
wc.style
= CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc
= WndProc;
wc.cbClsExtra
= 0 ;
wc.cbWndExtra
= 0 ;
wc.hInstance
= hInstance;
wc.hIcon
= ::LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor
= ::LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground
= (HBRUSH)::GetStockObject(BLACK_BRUSH);
wc.lpszMenuName
= NULL;
wc.lpszClassName
= lpszClassName;

RegisterClass(
& wc);

// WS_OVERLAPPEDWINDOW 可以改变窗口大小
// WS_OVERLAPPED 不可以改变窗口大小
// WS_POPUP 全屏
hwnd
= CreateWindow(lpszClassName,
TEXT(
" fangyukuan " ),
WS_OVERLAPPEDWINDOW
| WS_VISIBLE,
300 , 80 , 800 , 600 ,
NULL,
NULL,
hInstance,
NULL);

main_window_handle
= hwnd;

// ::ShowWindow(hwnd,SW_SHOWNORMAL);
// ::UpdateWindow(hwnd);
// while(::GetMessage(&msg,NULL,0,0))
// {
// ::TranslateMessage(&msg);
// ::DispatchMessage(&msg);
// }

Game_Init();
while (TRUE)
{
if (::PeekMessage( & msg, NULL, 0 , 0 , PM_REMOVE))
{
if (msg.message == WM_QUIT)
break ;
::TranslateMessage(
& msg);
::DispatchMessage(
& msg);
}
}
Game_Shutdown();
return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)

{
switch (message)
{
case WM_LBUTTONDOWN:
{
::MessageBeep(
0 );
}
break ;
case WM_DESTROY:
::PostQuitMessage(
0 );
break ;
default :
return ::DefWindowProc(hwnd,message,wParam,lParam);
}
return 0 ;
}

 程序运行效果:

 2011051323484587.png

转载请保留下面链接

http://www.cnblogs.com/fangyukuan/archive/2011/05/13/2045951.html



转载于:https://www.cnblogs.com/fangyukuan/archive/2011/05/13/2045951.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值