C:\Borland\CBuilder\ (對應 $(BCB))C:\dx5sdk\ (對應 $(DXSDK_DIR))BCB $(BCB)\Include 內建舊版 DirectX 標頭 (DX3/5/6),若直接在專案 Include 路徑 加入 $(DXSDK_DIR)\Include,編譯器會優先找到 BCB 內建舊版 導致定義衝突、缺少新介面。
最佳解法:將 DX SDK Include 目錄下所有檔案複製到 $(BCB)\Include 覆蓋。確保編譯器看到的是最新版 SDK 定義。
操作:xcopy /E /Y "C:\dx5sdk\Include\*.*" "C:\Borland\CBuilder\Include\"
DX SDK 隨附的 Borland 相容 .lib 可能有問題 (符號缺失、呼叫慣例不符)。建議下載社群修正版 (如 dx7b_bcb.lib、dx8b_bcb.zip) 解壓到 $(BCB)\Lib (或 $(BCB)\Lib\PSDK),並加入專案庫路徑。
WinMain、WndProc 進入點,不要 使用 VCL 應用程式精靈 (會拖入龐大 RTL、難以控制 DirectX 裝置建立時機)。<windows.h>, <d3d9.h>, <dinput.h> 等。
#if defined(__BORLANDC__) && defined(__WIN32__)
#define _WIN32
#endif
#define WIN32
#define WIN95 // 部分 DX 範例需此定義啟用特定代碼路徑
放在 stdafx.h 或專案選項 → Directories/Conditionals → Conditional defines。
// main.cpp
#define STRICT
#include
#include
#include
#pragma comment(lib, "d3d9.lib") // 需對應 BCB 版 d3d9.lib
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
HWND g_hWnd = NULL;
HRESULT InitD3D(HWND hWnd)
{
g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
if (!g_pD3D) return E_FAIL;
D3DPRESENT_PARAMETERS d3dpp = {0};
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
return g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice);
}
void Cleanup()
{
if (g_pd3dDevice) g_pd3dDevice->Release();
if (g_pD3D) g_pD3D->Release();
}
void Render()
{
if (!g_pd3dDevice) return;
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(0, 0, 100), 1.0f, 0);
if (SUCCEEDED(g_pd3dDevice->BeginScene())) {
// 繪製幾何體...
g_pd3dDevice->EndScene();
}
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_DESTROY: Cleanup(); PostQuitMessage(0); return 0;
case WM_PAINT: Render(); ValidateRect(hWnd, NULL); return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
_T("D3DWindow"), NULL };
RegisterClassEx(&wc);
g_hWnd = CreateWindow(_T("D3DWindow"), _T("BCB DirectX 9 Test"),
WS_OVERLAPPEDWINDOW, 100, 100, 640, 480,
NULL, NULL, hInst, NULL);
if (SUCCEEDED(InitD3D(g_hWnd))) {
ShowWindow(g_hWnd, SW_SHOWDEFAULT);
UpdateWindow(g_hWnd);
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT) {
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
Render(); // 空閒時持續渲染
}
}
}
UnregisterClass(_T("D3DWindow"), hInst);
return 0;
}
| 錯誤 | 原因 | 解決 |
|---|---|---|
未定義識別碼: IID_IDirect3D9 | 標頭檔版本舊/缺少 GUID 定義 | 重新複製 DX SDK Include 覆蓋、確認 initguid.h 包含順序 |
連結錯誤: Direct3DCreate9 未解析 | 缺少 d3d9.lib 或庫檔不相容 | 下載 BCB 相容庫、專案加入庫檔路徑、#pragma comment(lib, "d3d9.lib") |
執行錯誤: CreateDevice 失敗 (D3DERR_NOTAVAILABLE) | 裝置不支援要求格式/頂點處理模式 | 改用 D3DCREATE_HARDWARE_VERTEXPROCESSING 或 SOFTWARE_VERTEXPROCESSING、檢查 BackBufferFormat |
多重定義: GUID_... | 多個 .cpp 包含 initguid.h | 僅在一個 .cpp (通常主檔) 定義 #define INITGUID 再包含標頭 |
| DirectX 版本 | SDK 年份 | BCB 相容性 | 備註 |
|---|---|---|---|
| DirectX 7 | 1999 | 良好 | DX7 為 BCB 5/6 時代主流,範例最多 |
| DirectX 8/8.1 | 2000/2001 | 需修正庫 | 引入 Shader、頂點著色器 |
| DirectX 9.0c | 2004 | 需最新 BCB 修補包 + 社群庫 | 最終版,Shader Model 2/3,最長支援 |
| DirectX 10+ | 2006+ | 不支援 | 需 Vista+、WDDM 驅動,BCB 無法建立 D3D10+ 裝置 |
BCB 整合 DirectX 核心在於:標頭檔覆蓋更新、相容匯入庫、Win32 GUI 專案模板、必要前置定義。DX9 為 BCB 可支援的最高版本,新專案建議改用 Visual Studio + Windows SDK + DirectX 12/Agility SDK,獲得完整工具鏈、除錯層、效能分析 (PIX/Nsight) 支援。