一個簡單的DDraw應用程序

此文章轉載於: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; }
複製代碼

 程序運行效果:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章