DirectDraw6的初級程式設計應用 —— 配合例項講解,讓你迅速入門 (轉)
DirectDraw6的初級應用
by Gamster H. S
目錄:
1. VC的環境設定.
2. 淺談COM.
3. DirectDraw簡述.
4. DirectDraw的初級程式設計應用.
第一篇:VC的環境設定.
在進行任何有關的程式設計之前,你得先設定VC的環境變數值.主要是方便以後的專案設計.
我使用的是VC5和DirectX6,這是我的設定:
1. 選擇Options.
2. 選擇Directories Tab.
3. 在Show directories for框中選擇include files
4. 在Directories框中選擇一項新項,鍵入C:mssdkinclude,此目錄將含有所有有關的頭,
如:ddraw.h, dsound.h, ...
5. 在Show directories for框中選擇Library files
6. 在Directories框中選擇一項新項,鍵入C:mssdklib,此目錄將含有所有有關的庫檔案,
如:ddraw.lib, dsound.lib, dxguid.lib, ...
7. 選擇OK
當你編譯建立的程式時,以下是基本步驟是:
1. 將整個ddex1(c:mssdkmultimediaddrawddrawsrcddex1)目錄copy到你任為合適的目
錄中(如d:mydd,全稱為d:myddddex1).
2. 在VC5的選單項Files中選擇New.
3. 選擇 Application.
4. 鍵入合適的Location(如d:mydd).
5. 鍵入合適的Project Name(在此為ddex1).
6. 選擇選單項Project->Add to Project->Files,加入*.cpp檔案,*.rc檔案.在ddex1專案中,
你要加入ddex1.cpp和ddex1.rc檔案.
7. 選擇選單項Project->Settings,在Link中的/Library Modules中加入ddraw.lib
dxguid.lib.
8. Build and run.
9. Any prblems? You know where to find me!
第二篇:淺談COM.
我不大清楚,但沒幾個人混得清楚的.他們要麼知道點皮毛,要麼還在階段鍛練著.別人問
起,只說DirectX3,5,6運用許多COM技術.
第三篇:DirectDraw簡述.
DirectX大大提高在Win環境下的運用.DirectDraw提高各種顯示硬體的工作.
第四篇:DirectDraw的初級程式設計應用.
本文將簡述ddex1至ddex5中各種DirectDraw 的運用(in detail),至於更高的設計運用,望各位
自己慢慢從其他人手中學之.
1. DirectDraw例子中的全域性變數.
// Global data
LPDIRECTDRAW4 g_pDD = NULL; // DirectDraw object
LPDIRECTDRAWSURFACE4 g_pDDSPrimary = NULL;// DirectDraw primary surface
LPDIRECTDRAWSURFACE4 g_pDDSBack = NULL; // DirectDraw back surface
LPDIRECTDRAWSURFACE4 g_pDDSOne = NULL; // Offscreen surface 1
LPDIRECTDRAWPALETTE g_pDDPal = NULL; // The primary surface palette
BOOL g_bActive = FALSE; // Is application active?
以上全域性變數分別為:
1)IDirectDraw4的指標.用它建立其它幾個全域性變數.
2)IDirectDrawSue4的物件指標,在此是3個:
g_pDDSPrimary是顯示緩衝塊,用於顯示;
g_pDDSBack是幕後顯示緩衝塊,從後屏緩衝區截圖後拼在此緩衝塊上,隨後翻成顯示緩衝
塊,原有顯示緩衝塊翻成幕後顯示緩衝塊;
g_pDDSOne是後屏緩衝區,用於不同圖形資料.
3)IDirectDrawPalette的物件指標,用於儲存特定BITMAP的調色盤.用在Color manipulation.
4)另一變數和DirectDraw無任何關係.只是確認是否處於執行狀態.
以上的編碼含有說明,所以對任何人都易理解.Any problems? You know where to find me!
2.初始化所有全程變數
這些原碼我抄自ddex5.cpp中的static HRESULT InitApp(HINSTANCE hInstance, int nCmdShow)中:
1)定義幾個區域性變數:
DDSURFACEDESC2 ddsd; // the structure contain information about a particluar DirectDrawSurface.
DDSCAPS2 ddscaps; // this is important for further step
HRESULT hRet; // error output
LPDIRECTDRAW pDD; // IDirectDraw Object.
2)組建各項物件:
///////////////////////////////////////////////////////////////////////////
// Create the main DirectDraw object
///////////////////////////////////////////////////////////////////////////
hRet = DirectDrawCreate(NULL, &pDD, NULL);
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "DirectDrawCreate FAILED");
先建立一個IDirectDraw Object,hRet裝有DirectDrawCreate()的返回值,這一招非常有用,所有的DirectX
函式都返回一定的數值,DirectDraw的函式返回DD_OK表示函式成功.DDERR_***的返回值表示函式
呼叫失敗(或其他原因).檢查函式返回值,以備以後布驟不會出錯.我將推遲解釋InitFail()函式.
// Fetch DirectDraw4 interface
hRet = pDD->QueryInterface(IID_IDirectDraw4, (LPVOID *) & g_pDD);
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "QueryInterface FAILED");
我們用COM中的QueryInterface申請一個IDirectDraw4物件,不同於DIRECTX5,DirectDraw增加了IDirectDraw4
介面,同時新增了幾個更有用的函式(METHODS).你可以從DirectX的幫助檔案中查到.雖是英文,
但好好啃一啃還是有收穫的.
// Get exclusive mode
hRet = g_pDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "SetCooperativeLevel FAILED");
我們接著設定顯示方式,你可設定全屏,或視窗型,或MODEX,從DDEX1到DDEX5的程式中使用的顯
示方式都是DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN,全屏!你可以從DirectX的幫助檔案中查到有關
SetCooperativeLevel()的註解.雖是英文,但好好啃一啃還是有收穫的.
// Set the vo mode to 640x480x8
hRet = g_pDD->SetDisplayMode(640, 480, 8, 0, 0);
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "SetDisplayMode FAILED");
我們接著設定螢幕大小,色素和重新整理速度.你可以從DirectX的幫助檔案中查到有關SetDisplayMode()的
註解.雖是英文,但好好啃一啃還是有收穫的.全屏下你所設顯示可為320X200, 640X480, 800X600,
1024X768, 1280X1024, 1600X1280等等.色素從8, 16, 24, 32BITs.
// Create the primary surface with 1 back buffer
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FL|
DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
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
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
hRet = g_pDDSPrimary->GetAttachedSurface(&ddscaps, &g_pDDSBack);
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "GetAttachedSurface FAILED");
建立一顯示緩衝塊附帶一塊幕後顯示緩衝塊.首先你初始化DDSURFACEDESC2的物件.如下:
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); // you will fail without this!!
我觀查到的現象是,每個DirectDraw結構含有dwSize成員,一定要初始化這個成員如下:
ddStructObj.dwSize = sizeof(DDSTRUCT); // you will fail without this!!
以下一段編碼
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
DDSCAPS_FLIP |
DDSCAPS_COMPLEX;
表示所建DirectDrawSurface是Primary Surface(顯示緩衝塊),Flipable(前後翻轉),有Back Buffer
(幕後顯示緩衝塊)連線到Primary Surface(attached to).
ddsd.dwBackBufferCount = 1;
表示Back Buffer(幕後顯示緩衝塊)只有一塊.
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
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
hRet = g_pDDSPrimary->GetAttachedSurface(&ddscaps, &g_pDDSBack);
if (hRet != DD_OK)
return InitFail(hWnd, hRet, "GetAttachedSurface FAILED");
這一段編碼建立Primary Surface,再建立Back Buffer.至此我們的初始工程基本結束!
3.出錯處理.
現在介紹初始化過程中錯誤的處理.
return InitFail(hWnd, hRet, "...... FAILED");
這一語段的運用是,當某一步初始化過程出錯,整個程式退出,並顯示一個對話方塊.其定義如下:
// Name: InitFail()
// Desc: This function is called if an initialization function fails
HRESULT InitFail(HWND hWnd, HRESULT hRet, LPCTSTR szError,...)
{
char szBuff[128];
va_list vl;
va_start(vl, szError);
vsprintf(szBuff, szError, vl);
ReleaseAllObjects();
MessageBox(hWnd, szBuff, TITLE, MB_OK);
DestroyWindow(hWnd);
va_end(vl);
return hRet;
}
你要增寫一個RelaeseAllObject()函式,此函式將釋放所有的DDRAW物件.有一點值得申明.如果對
象早已被釋放,程式不知,試圖釋放不存在的物件將有嚴重後果,小心!!!!
// Name: ReleaseAllObjects()
// Desc: Finished with all objects we use; release them
static void ReleaseAllObjects(void)
{
if (g_pDD != NULL)
{
if (g_pDDSPrimary != NULL)
{
g_pDDSPrimary->Release();
g_pDDSPrimary = NULL;
}
if (g_pDDSOne != NULL)
{
g_pDDSOne->Release();
g_pDDSOne = NULL;
}
if (g_pDDPal != NULL)
{
g_pDDPal->Release();
g_pDDPal = NULL;
}
g_pDD->Release();
g_pDD = NULL;
}
}
這裡,程式先釋放IDirectDraw4下屬的物件,再釋放IDirectDraw4的物件.釋放前,程式先確認各對
象是否存在,如物件還駐留於內村中,釋放物件,並賦值物件指標NULL.
4.如何恢復暫時丟失的物件值.
在你按ALT+TAB鍵後,應用程式相互切換,當你從其他應用程式轉換到DirectDraw有關應用程式時,原
有的物件緩衝區將在切換過程中被I/O釋放.稱為丟失(LOST).要重新建立.只有IDirectDraw4對
象屬下的IDirectDrawSuface4物件有丟失的可能,所以IDirectDrawSurface4提供了Restore()程式.使用方式
如下:
// Name: RestoreAll()
// Desc: Restore all lost objects
HRESULT
RestoreAll(void)
{
HRESULT hRet;
hRet = g_pDDSPrimary->Restore();
if (hRet == DD_OK)
{
hRet = g_pDDSOne->Restore();
if (hRet == DD_OK)
{
// 重新將Bitmap讀入.DDReloaitmap()
}
}
return hRet;
}
一般,DirectDrawSuface4物件的丟失將沖刷物件所含的Bitmap.故要使用DDReLoadBitmap()函式重新從
Bitmap檔案中讀入記憶體.此函式收藏於DDUTIL.CPP檔案中.並不屬於DirectX的一部分.下面,就讓我
介紹如何使用DDUTIL.CPP中的函式.
5.使用DirectDraw Utilities!!
為了方便開發者,初學者對DirectX的困惑,MS DirectX設計組專門寫了一個DDUTIL.CPP檔案來幫助大
家.它提供了方便的函式來進行讀取Bitmap並賦值於IDirectDrawSurface4物件,從Bitmap中讀取調色盤
資訊,設定透明色等方程.定義如下:
/*==========================================================================
* File: ddutil.cpp
* Content: Routines for loading bitmap and palettes from res
***************************************************************************/
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif /* __cplusplus */
extern IDirectDrawPalette *DDLoadPalette(IDirectDraw4 *pdd, LPCSTR szBitmap);
extern IDirectDrawSurface4 *DDLoadBitmap(IDirectDraw4 *pdd, LPCSTR szBitmap, int dx, int dy);
extern HRESULT DDReLoadBitmap(IDirectDrawSurface4 *pdds, LPCSTR szBitmap);
extern HRESULT DDCopyBitmap(IDirectDrawSurface4 *pdds, HBITMAP hbm, int x, int y, int dx, int dy);
extern D DDColorMatch(IDirectDrawSurface4 *pdds, COLORREF rgb);
extern HRESULT DDSetColorKey(IDirectDrawSurface4 *pdds, COLORREF rgb);
#ifdef __cplusplus
}
#endif /* __cplusplus */
-> DDLoadPalette(IDirectDraw4 *pdd, LPCSTR szBitmap):
從Bitmap檔案中讀出調色盤資訊,並將此資訊交送於IDirectDraw4的物件.
1)引數IDirectDraw4 *是IDirectDraw4的物件指標.
2)引數LPCSTR,是Bitmap檔案全名.
3)使用例項:
g_pDDPal = DDLoadPalette(g_pDD, "C:hanmybitmap1.bmp");
if (g_pDDPal)
g_pDDSPrimary->SetPalette(g_pDDPal);
4)詳情請參閱DDEX3-5.CPP
->DDLoadBitmap(IDirectDraw4 *pdd, LPCSTR szBitmap, int dx, int dy):
建立一塊含有指定Bitmap的IDirectDrawSurface4物件,先建立一塊足以容納指定Bitmap的IDirectDrawSurface4
物件.再將Bitmap讀入記憶體.
1)引數IDirectDraw4 *是物件指標.
2)引數LPCSTR,是Bitmap檔案全名.
3)dx, dy表示Bitmap大小.
4)使用例項:
g_pDDSOne = DDLoadBitmap(g_pDD, "C:hanmybitmap.bmp", 640, 490);
if(g_pDDSOne == NULL)
{
// Abort the program.
}
5)沒有例項,多試試.
->DDReLoadBitmap(IDirectDrawSurface4 *pdds, LPCSTR szBitmap):
把一塊Bitmap讀入一個指定的IDirectDrawSurface4物件指標.
1)引數IDirectDrawSurface4 *是物件指標,將接收Bitmap.
2)引數LPCSTR,是Bitmap檔案全名.
3)使用例項:
hRet = DDReLoadBitmap(g_pDDSOne, "C:hanmybitmap.bmp");
if(FAILED(hret))
{
// Abort the program.
}
4)詳情請參閱DDEX3-5.CPP
5)我用此函式最多.
->DDCopyBitmap(IDirectDrawSurface4 *pdds, HBITMAP hbm, int x, int y, int dx, int dy):
You don't need to know.
->DDColorMatch(IDirectDrawSurface4 *pdds, COLORREF rgb):
You don't need to know.
->DDSetColorKey(IDirectDrawSurface4 *pdds, COLORREF rgb):
在指定的引數IDirectDrawSurface4的物件指標上設定一transparent Colorkey.
1)引數IDirectDrawSurface4 *是物件指標,將接收ColorKey.
2)COLORREF, Colorkey的數值.
3)使用例項:
hRet = DDReLoadBitmap(g_pDDSOne, "C:hanmybitmap.bmp");
if(FAILED(hret))
{
// Abort the program.
}
4)詳情請參閱DDEX3-5.CPP
5)我用此函式也很多.
For more information about those functions, you better observe the examples provided (DDEX1 - DDEX5) for
details.It is the easy way. All the implementations about those functions is in DDUTIL.CPP file.
6.BLIT, FLIP, &Color fill.
這三個應用是DirectDraw的主要應用.其功能為在BackBuffer上畫上Bitmap圖塊,或填上一定的顏色,
再翻到螢幕上.所用函式為:
1>.Blt和BltFast在BackBuffer上畫上Bitmap圖塊.
Example;
RECT rcRect;
rcRect.left = 0;
rcRect.top = 0;
rcRect.right = 640;
rcRect.bottom = 480;
while(1) {
ddrval = g_pDDSBack->BltFast(0, 0, g_pDDSOne, &rcRect, DDBLTFAST_WAIT);
if(ddrval == DD_OK)
{
break;
}
else if(ddrval == DDERR_SURFACELOST)
{
// use the restore all function!
RestoreAll();
}
}
我常用Blt function:
Example;
RECT srcRect = {0, 0, 640, 480};
RECT dstRect = {0, 0, 640, 480};
DDBLTFX tempFX; // you will fail if you don't have this!
tempFX.dwsize = sizeof(DDBLTFX); // you will fail if you don't have this!
while(1) {
ddrval = g_pDDSBack->Blt(dstRect, g_pDDSOne, srcRect, DDBLT_WAIT, &tempFX);
if(ddrval == DD_OK)
{
break;
}
else if(ddrval == DDERR_SURFACELOST)
{
// use the restore all function!
RestoreAll();
}
else if(ddrval != DDERR_WASSTILLDRAWING)
{
break;
}
}
若想使用透明色(COLORKEY),改DDBLTFAST_WAIT(BltFast的最後一個引數)為
DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY. 改DDBLT_WAIT(Blt的倒數第二個引數)為
DDBLT_WAIT | DDBLT_COLORSRC.
2.>用Blt在BackBuffer上填充顏色,(我從未成功過).
RECT dstRect = {0, 0, 640, 480};
DDBLTFX tempFX; // you will fail if you don't have this!
tempFX.dwsize = sizeof(DDBLTFX); // you will fail if you don't have this!
tempFX.dwFillColor = RGB(0, 255, 0); // green.
while(1) {
ddrval = g_pDDSBack->Blt(dstRect, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &tempFX);
if(ddrval == DD_OK)
{
break;
}
else if(ddrval == DDERR_SURFACELOST)
{
// use the restore all function!
RestoreAll();
}
else if(ddrval != DDERR_WASSTILLDRAWING)
{
break;
}
}
這個例碼將在dstRect(0, 0, 640, 480)的長方形中填充綠色.長方形的大小和位置以你定義
的RECT物件確定.用Blt和BltFast的幾個弱點是:
1)當dstRect(目標長方塊)不和srcRect(源長方塊)大小一致,Blt和BltFast將十分慢.
2)當dstRect部分超出螢幕,如螢幕大小640X480,你想在長方塊{500, 500, 800, 600}中顯示
圖塊,此圖塊不將處顯,因為你定義的圖塊在螢幕以外!解決方法將在續篇(Advanced Section)中提出.
3.>使用Flip:
將準備好的BackBuffer翻到螢幕上,原來的Primar Surface變成BackBuffer.
while(1) {
ddrval = g_pDDSPrimary->Flip(NULL, DDFLIP_WAIT);
if(ddrval == DD_OK)
{
break;
}
else if(ddrval == DDERR_SURFACELOST)
{
// use the restore all function!
RestoreAll();
}
else if(ddrval != DDERR_WASSTILLDRAWING)
{
break;
}
}
4.總結:
1) 建立暫時的IDirectDraw物件.
2) 用COM中的QueryInterface來建立IDirectDraw4的物件.
3) SetCooperativeLevel (視窗或全屏).
4) SetDisplayMode(螢幕大小,色度,重新整理速度).
5) 建立primary surface(螢幕顯示記憶體),back buffer(幕後顯示記憶體),和off-screen sufaces(備用顯示記憶體,用於
儲存圖塊).
6) 使用ddutil檔案中的函式來讀入Bitmap,設定ColorKey(當你進行Blt操作,這種顏色將不被顯示).
7) 用Blt和BltFast將圖塊打入back buffer,用Flip來將準備好的back buffer翻成primary surface.原有的
primary surface翻成back buffer,等待下一輪Blt和BltFast的呼叫.
這些是DirectDraw版本6中的基本操作!我將寫一個續篇(Advanced Section).Enjoy programming!
請大膽提出問題,寫信給我或留言於留言板!感謝Doug Klopfenstein!他的Basic DirectDraw Programming
(譚翁編譯了這一文章!)給我很大幫助.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-988059/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Shell程式設計入門例項程式設計
- 【Akka】Akka入門程式設計例項程式設計
- 程式設計“初學者”入門指南 (轉)程式設計
- 演算法設計應用例項 (轉)演算法
- 混合移動應用開發初級例項
- Promise入門到精通(初級篇)-附程式碼詳細講解Promise
- 設計支援載入項的應用程式
- [翻譯]返回導向程式設計例項入門程式設計
- Maven例項講解教程,從零開始學Maven,帶你快速入門!Maven
- 入門級的程式設計師程式設計師
- 設計模式 - 原則及例項講解設計模式
- 設計模式例項講解 - 里氏替換設計模式
- 設計模式例項講解 - 介面隔離設計模式
- 設計模式例項講解 - 依賴倒置設計模式
- python socket程式設計入門(編寫server例項)Python程式設計Server
- 初級程式設計師應該瞭解的Linux命令程式設計師Linux
- Go Web 程式設計入門--應用 ORMGoWeb程式設計ORM
- Android RxJava應用例項講解:你該什麼時候使用RxJava?AndroidRxJava
- XML程式設計例項(二) (轉)XML程式設計
- 設計模式例項講解 - 開放封閉設計模式
- java程式設計入門指南,你應該瞭解的Java小知識Java程式設計
- Spring程式設計式和宣告式事務例項講解Spring程式設計
- Matlab圖形使用者介面程式設計初級入門Matlab程式設計
- 再談應用程式的例項問題 (轉)
- 例項講解:我的強化學習初體驗!強化學習
- 智慧領域物件設計(例項講解)-2/2物件
- 【深度學習】--DCGAN從入門到例項應用深度學習
- TCSHshell程式設計入門(轉)程式設計
- Linux程式設計入門 - zlib的運用(轉)Linux程式設計
- Go Web 程式設計入門--應用資料庫GoWeb程式設計資料庫
- 白色在網頁設計中的應用例項網頁
- Python設計模式之"外觀模式"例項講解Python設計模式
- 超級簡單入門vuex 小例項Vue
- grafana初級入門Grafana
- 最詳細的測試用例設計方法講解
- 程式設計入門,這763位老程式設計師有話講!程式設計師
- 初級程式設計師考試大綱 (轉)程式設計師
- 求助!!!求jdon的原始碼,“Struts應用系統案例設計程式設計講解”原始碼程式設計