DirectX

DirectX is a group of low-level application programs of application programming interface (API) for creating games and other demanding multimedia applications. It includes support for 2D and 3D graphics, sound and music, input, and network communication for applications such as multiplayer games. DirectX is over the layer of the operating system Microsoft Windows; this means that the programmer can use 32 bit memory addressing (no longer the old 16 bit one) for writing into Segment, Offset, a flat memory model, where memory is available from 0 to MAX, where 'MAX' is the maximum size of this memory. At present, there is a current release 7.0 containing also support for new technologies, like for example 3D sound, hardware transformation of objects and light (T&L), support of 3DNOW! commands.

DirectX contains the following components:

    DirectDraw a program interface enabling direct access to the memory of a display rendering adapter with its emphasis on compatibility with the Windows graphics device interface(GDI. DirectDraw represents a hardware independent solution, using two layers: The hardware abstraction layer (HAL), in fact the set of commands is identical in every computer configuration, and when DirectX finds that the given device supports the corresponding instruction through hardware, it uses these hardware functions, and if it does not need them, then such an instruction is interpreted via software using all available means; and the hardware emulation layer (HEL). (All commands are available, however, they are run via software). This mode is used mainly in the single step operations of programs. Both these methods are also used in all interfaces of other types of DirectDraw.

    Direct3D - an extension of the DirectDraw interface for 3D graphics. Here the programmer can select from the two following types: Immediate Mode or Retained Mode.. The Immediate Mode is used mainly by professional programmers because it provides direct access to hardware graphics cards. In this mode, it works with individual polygons and lights. The Retained Mode is used mainly by new programmers or those, who do not require control over every displayed pixel on the screen. This mode enables simple use of objects, whole animations of camera lights, collision of objects, and many other useful features.

   DirectInput - an interface for input devices, like for instance: keyboard, joystick, and other game devices, including force-back devices, enabling feedback on actions in a game.

   DirectMusic - an interface for playing of music. Only for DirectX 6.0 and higher.

   DirectSound - an interface for controlling music. This also includes 3D sound effects.

   DirectPlay - an interface for network communications. Uses interfaces IPX, TCP/IP.



Here is an example of DirectX application for Delphi and DirectX in release 7:

uses uses
Windows, Messages, DirectDraw, SysUtils;

{$R *.res}

const
//---------------------------------------------------------------------------
// Local definitions
//---------------------------------------------------------------------------
NAME : PChar = 'DDExample1';
TITLE : PChar = 'Direct Draw Example 1';

//---------------------------------------------------------------------------
// Default settings
//---------------------------------------------------------------------------
TIMER_ID = 1;
TIMER_RATE = 500;

var
//---------------------------------------------------------------------------
// Global data
//---------------------------------------------------------------------------
g_pDD : IDirectDraw7; // DirectDraw objekt
g_pDDSPrimary : IDirectDrawSurface7; // DirectDraw primary surface
g_pDDSBack : IDirectDrawSurface7; // DirectDraw back surface
g_bActive : Boolean = False; // Is application active?

//---------------------------------------------------------------------------
// Local data
//---------------------------------------------------------------------------
szMsg : PChar = 'Page Flipping Test: Press F12 to exit';
szFrontMsg : PChar = 'Front buffer (F12 to quit)';
szBackMsg : PChar = 'Back buffer (F12 to quit)';

//-----------------------------------------------------------------------------
// Name: ReleaseAllObjects
// Desc: Finished with all objects we use; release them
//-----------------------------------------------------------------------------
procedure ReleaseAllObjects;
begin
if Assigned(g_pDD) then
begin
if Assigned(g_pDDSBack) then
begin
g_pDDSBack := nil;
end;
if Assigned(g_pDDSPrimary) then
begin
g_pDDSPrimary := nil;
end;
g_pDD := nil;
end;
end;

//-----------------------------------------------------------------------------
// Name: InitFail
// Desc: This function is called if an initialization function fails
//-----------------------------------------------------------------------------
function InitFail(h_Wnd : HWND; hRet : HRESULT; Text : string) : HRESULT;

begin
ReleaseAllObjects;
MessageBox(h_Wnd, PChar(Text + ': ' + DDErrorString(hRet)), TITLE,
MB_OK);
DestroyWindow(h_Wnd);
Result := hRet;
end;

//-----------------------------------------------------------------------------
// Name: UpdateFrame
// Desc: Displays the proper text for the page
//-----------------------------------------------------------------------------
var
phase : Boolean = False;

procedure UpdateFrame(h_Wnd : HWND);
var
h_DC : HDC;
ddbltfx : TDDBltFx;
rc : TRect;
size : TSize;
begin
// Use the blter to do a color fill to clear the back buffer
FillChar(ddbltfx, SizeOf(ddbltfx), 0);
ddbltfx.dwSize := SizeOf(ddbltfx);
ddbltfx.dwFillColor := 0;
g_pDDSBack.Blt(nil, nil, nil, DDBLT_COLORFILL or DDBLT_WAIT,
@ddbltfx);

if g_pDDSBack.GetDC(h_DC) = DD_OK then
begin
SetBkColor(h_DC, RGB(0, 0, 255));
SetTextColor(h_DC, RGB(255, 255, 0));
if phase then
begin
GetClientRect(h_Wnd, rc);
GetTextExtentPoint(h_DC, szMsg, StrLen(szMsg), size);
TextOut(h_DC, (rc.right - size.cx) div 2, (rc.bottom - size.cy) div 2, szMsg,
StrLen(szMsg));
TextOut(h_DC, 0, 0, szFrontMsg, StrLen(szFrontMsg));
phase := False;
end
else
begin
TextOut(h_DC, 0, 0, szBackMsg, StrLen(szBackMsg));
phase := True;
end;
g_pDDSBack.ReleaseDC(h_DC);
end;
end;

//-----------------------------------------------------------------------------
// Name: WindowProc
// Desc: The Main Window Procedure
//-----------------------------------------------------------------------------
function WindowProc(h_Wnd: HWND; aMSG: Cardinal; wParam: Cardinal;
lParam: Integer) : Integer; stdcall;
var
hRet : HRESULT;
begin
case aMSG of
// Pause if minimized
WM_ACTIVATE:
begin
if HIWORD(wParam) = 0 then
g_bActive := True
else
g_bActive := False;
Result := 0;
Exit;
end;
// Clean up and close the app
WM_DESTROY:
begin
ReleaseAllObjects;
PostQuitMessage(0);
Result := 0;
Exit;
end;
// Handle any non-accelerated key commands
WM_KEYDOWN:
begin
case wParam of
VK_ESCAPE,
VK_F12:
begin
PostMessage(h_Wnd, WM_CLOSE, 0, 0);
Result := 0;
Exit;
end;
end;
end;
// Turn off the cursor since this is a full-screen app
WM_SETCURSOR:
begin
SetCursor(0);
Result := 1;
Exit;
end;
// Update and flip surfaces
WM_TIMER:
begin
if g_bActive and (TIMER_ID = wParam) then
begin
UpdateFrame(h_Wnd);
while True do
begin
hRet := g_pDDSPrimary.Flip(nil, 0);
if hRet = DD_OK then
Break;
if hRet = DDERR_SURFACELOST then
begin
hRet := g_pDDSPrimary._Restore;
if hRet <> DD_OK then
Break;
end;
if hRet <> DDERR_WASSTILLDRAWING then
Break;
end;
end;
end;
end;

Result := DefWindowProc(h_Wnd, aMSG, wParam, lParam);
end;

//-----------------------------------------------------------------------------
// Name: InitApp
// Desc: Do work required for every instance of the application:
// Create the window, initialize data
//-----------------------------------------------------------------------------
function InitApp(hInst : THANDLE; nCmdShow : Integer) : HRESULT;
var h_Wnd : HWND;
wc : WNDCLASS;
ddsd : TDDSurfaceDesc2;
ddscaps : TDDSCaps2;
hRet : HRESULT;
pDDTemp : IDirectDraw;
begin
// Set up and register window class
wc.style := CS_HREDRAW or CS_VREDRAW;
wc.lpfnWndProc := @WindowProc;
wc.cbClsExtra := 0;
wc.cbWndExtra := 0;
wc.hInstance := hInst;
wc.hIcon := LoadIcon(hInst, 'MAINICON');
wc.hCursor := LoadCursor(0, IDC_ARROW);
wc.hbrBackground := GetStockObject(BLACK_BRUSH);
wc.lpszMenuName := NAME;
wc.lpszClassName := NAME;
RegisterClass(wc);

// Create a window
h_Wnd := CreateWindowEx(WS_EX_TOPMOST,
NAME,
TITLE,
WS_POPUP,
0,
0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
0,
0,
hInst,
nil);

if h_Wnd = 0 then
begin
Result := 0;
Exit;
end;

ShowWindow(h_Wnd, nCmdShow);
UpdateWindow(h_Wnd);
SetFocus(h_Wnd);


///////////////////////////////////////////////////////////////////////////
// Create the main DirectDraw object
///////////////////////////////////////////////////////////////////////////


hRet := DirectDrawCreate(nil, pDDTemp, nil);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'DirectDrawCreate FAILED');
Exit;
end;
hRet := pDDTemp.QueryInterface(IDirectDraw7, g_pDD);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'QueryInterface FAILED');
Exit;
end;
pDDTemp := nil;

// Adjust called "Exclusive mode"
hRet := g_pDD.SetCooperativeLevel(h_Wnd, DDSCL_EXCLUSIVE or
DDSCL_FULLSCREEN);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'SetCooperativeLevel FAILED');
Exit;
end;

// Adjust 640x480x8
hRet := g_pDD.SetDisplayMode(640, 480, 8, 0, 0);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'SetDisplayMode FAILED');
Exit;
end;

// Create primary surface with one back buffer
FillChar(ddsd, SizeOf(ddsd), 0);
ddsd.dwSize := SizeOf(ddsd);
ddsd.dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE or
DDSCAPS_FLIP or DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount := 1;
hRet := g_pDD.CreateSurface(ddsd, g_pDDSPrimary, nil);

if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'CreateSurface FAILED');
Exit;
end;

// Find director na back buffer
FillChar(ddscaps, SizeOf(ddscaps), 0);
ddscaps.dwCaps := DDSCAPS_BACKBUFFER;
hRet := g_pDDSPrimary.GetAttachedSurface(ddscaps, g_pDDSBack);
if hRet <> DD_OK then
begin
Result := InitFail(h_Wnd, hRet, 'GetAttachedSurface FAILED');
Exit;
end;

// Create timer on changing pages
if TIMER_ID <> SetTimer(h_Wnd, TIMER_ID, TIMER_RATE, nil) then
begin
Result := InitFail(h_Wnd, hRet, 'SetTimer FAILED');
Exit;
end;

Result := DD_OK;
end;

var aMSG : MSG;
begin
if InitApp(GetModuleHandle(nil), SW_SHOW) <> DD_OK then
begin
Exit;
end;

while GetMessage(aMSG, 0, 0, 0) do
begin
TranslateMessage(aMSG);
DispatchMessage(aMSG);
end;

end.

Used sources:
    Microsoft SDK Help for DirectX7, Microsoft help file, 20.September 1999

Copyright (c) 1999-2017 Juraj Štugel. www.netgraphics.sk