此文章轉載於:http://www.cnblogs.com/fangyukuan/archive/2011/05/13/2045951.html
DDraw總共由五個接口組成:
IUnknown:所有com接口都必須從這裏繼承的。(請看相關文章COM筆記-QueryInterface函數)
IDirectDraw:使用DDraw必須創建的主接口對象。
IDirectDrawSurface:創建、控制和顯示的實際顯示錶面。分主顯示錶面和從顯示錶面
IDirectDrawPalette:創建、加載和控制調色板,以及將它關聯到顯示錶面。
IDirectDrawClipper:剪切DDraw光柵和位圖操作到一些可見顯示錶面的子集。
這些接口怎麼配合起來成爲一個DDraw應用程序的:
1. 創建DDraw對象並使用QueryInterface()來得到 一個IDirectDraw7接口,或是直接用DirectDrawCreateEx()創建一個DDraw7接口。用這個接口來設置協作級別和視頻模式。
2. 使用IDirectDrawSurface7接口至少創建 一個主顯示錶面用以繪圖。(如果每個像素爲8位或更少我們會用到一個調色板)
3. 用IDirectDrawPalette接口創建 一個調色板。(注意如果像素高於8位,如16位、24位,32位,沒有調色板,現在主流2D遊戲多數是16色)
4. 如果DDraw應用程序要使用窗口,或者要減少位圖以免溢出DDraw顯示錶面的可見邊界,我們至少需要合建一個剪裁器並將其尺寸設置爲可見窗口的範圍。如下圖
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
// 創建者 : 方煜寬
// 郵箱 : [email protected]
// 創建時間 : 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;
}
程序運行效果: