|
TUTORIAL -
INSIDE
THE
TDx_LIBRARY
|
|
This tutorial is best viewed maximized, in 1024 x 768 screen resolution or better.
OVERVIEW OF USING THE TDX_LIBRARY
Top
Next
The TDx_Library "wraps" DirectX on a 1:1 basis.
For those not familiar with "wrappers", the idea is that all available DirectX functionality is
translated and modified where necessary from Microsoft's "hungarian notation" style of programming
to the much easier Visual Component Library (VCL) style of programming used in Borland C++ Builder.
They say a picture is worth a thousand words, so here is an attempt :-
In essence, the TDx_Library builds onto existing DirectX functionality while
adding extra functionality around the DirectX core designed to help you create results quicker.
INSIDE THE TDX_LIBRARY
Top
Next
Prev
Understanding the DirectX to TDx_Library relationship is easy:
Above you can see some of the TDx_Draw_Library components highlighted on the Component Palette.
The components on this palette represent all the different sections of DirectDraw wrapped into BCB components,
each component translating all available features in a particular section of DirectDraw to it's VCL equivalent,
with the end-result component wrapping and incorporating all DirectDraw functionality on a 1:1 basis.
eg:
- TDDBltFX wraps the DDBLTFX structure
- TDDCaps wraps the DDCAPS structure
- TDDColorKey wraps the DDCOLORKEY structure
...
- TDx_Draw wraps the IDirectDraw7 interface
- TDx_DrawClipper wraps the IDirectDrawClipper interface
- TDx_DrawColorControl wraps the IDirectDrawColorControl interface
...
- and so on, one component for each DirectDraw structure or interface.
By dragging and dropping these components, setting up properties, adding some vcl code, you are indeed programming with DirectDraw, or DirectSound, or DirectInput or DirectPlay or Direct3DI.
These components are really 3 distinct types, all derived from the standard BCB TComponent:
- Wrappers
- Multi Wrappers
- Interface Wrappers
Each of these 3 component types is designed to wrap a particular feature of DirectX.
- Wrappers wrap a single DirectX structure
- Multi Wrappers wrap and manage a dynamic array of DirectX structures
- Interface Wrappers wrap an individual DirectX COM interface
More information on each of the individual wrapper types is located below.
WRAPPERS
Top
Next
Prev
A "Wrapper" component type takes a standard DirectX Structure Definition, and translates it to work in BCB.
For example, below is the DDCOLORCONTROL structure definition defined within DirectDraw:
struct DDCOLORCONTROL
{
DWORD dwSize;
DWORD dwFlags;
LONG lBrightness;
LONG lContrast;
LONG lHue;
LONG lSaturation;
LONG lSharpness;
LONG lGamma;
LONG lColorEnable;
DWORD dwReserved1;
};
In "TDx_Library" terms, this becomes a standard vcl-style component:
class TDDColorControl : public TComponent
{
// properties:
__property dword Size;
__property dword Flags;
__property long Brightness;
__property long Contrast;
__property long Hue;
__property long Saturation;
__property long Sharpness;
__property long Gamma;
__property long ColorEnable;
__property HRESULT ErrorValue;
__property DDCOLORCONTROL* Internal_DDCOLORCONTROL_Ptr;
__property AnsiString Flags_Strings;
// methods:
void __fastcall Clear();
void __fastcall Internal_DDCOLORCONTROL_Update();
// events:
__property TDx_Error OnError();
// internals:
DDCOLORCONTROL fDDCOLORCONTROL;
};
a standard vcl-style component can be setup at design time:
and can also be setup a runtime using vcl-style code:
with automatic error detection:
additional components are similar, but different:
See these bits?
// properties:
__property HRESULT ErrorValue;
__property DDCOLORCONTROL* Internal_DDCOLORCONTROL_Ptr;
__property AnsiString Flags_Strings;
// methods:
void __fastcall Clear();
void __fastcall Internal_DDCOLORCONTROL_Update();
// events:
__property TDx_Error OnError();
// internals:
DDCOLORCONTROL fDDCOLORCONTROL;
This is what they are used for:
__property HRESULT ErrorValue;
This property contains the last DirectX or TDx_Library error code that was automatically detected by
the wrapper component. This is usually an "out-of-range" error.
__property DDCOLORCONTROL* Internal_DDCOLORCONTROL_Ptr;
This property allows direct access to the internal DirectX structure, as is sometimes required.
(Advanced Tip) when you copy data into a wrapper's internal structure using this property, and the
VCL part of this component has already been linked to other component, you can auto-cascade your
data into all linked TDx_Library components by calling the Internal_DDCOLORCONTROL_Update() method.
__property AnsiString Flags_Strings;
Whenever a component property has flags, a corresponding '_Strings' property is available for instant
text retrieval of the currently set flags. For example, DDCaps1 (above) has Caps2, Caps, FXAlphaCaps, NLVBCaps2, etc.
It also has text variants called 'Caps2_Strings', 'Caps_Strings', 'FXAlphaCaps_Strings', 'NLVBCaps2_Strings', etc.
void __fastcall Clear();
This method clears the internal structure's content, and if required, it resets dwSize to sizeof(DDCOLORCONTROL), or other structure.
void __fastcall Internal_DDCOLORCONTROL_Update();
This method is mostly used internally by the TDx_Library to maintain data integrity throughout different components that are linked together.
For example, you can link a TDDSurfaceDesc::Caps property to a TDDSCaps component, and a
TDDSurfaceDesc::PixelFormat property to a TDDPixelFormat component, then
when the TDDSurfaceDesc's internal DDSURFACEDESC structure is modified, a call to the
TDDSurfaceDesc::Internal_DDSURFACEDESC_Update() will automatically update the linked components
internal data structures.
__property TDx_Error OnError();
This event is automatically called by the error detection code for each method,
and can usually be setup as a one-stop-shop for all error handling code.
DDCOLORCONTROL fDDCOLORCONTROL
This is the internal storage of the DirectX DDCOLORCONTROL structure.
(Advanced Tip) All the properties have FGet() & FSet() methods, which are used to auto-translate from DirectX to BCB,
some have auto error-detection, and where possible, the DirectX structure elements are manipulated directly. For more complex
translations, some DirectX structure elements are manipulated in tandem with BCB "shadow" elements.
MULTI WRAPPERS
Top
Next
Prev
A "MultiWrapper" component is basically the same as a "Wrapper Component", except that it translates
and automatically manages an array of structures internally instead of a single DirectX structure.
These components are implemented where an array of structures is required to be passed to DirectX,
and also when it is more convenient to store an array of data structures within the same component, ie. to save resources.
Note that MultiWrapper components are used at runtime due to their dynamic nature.
As a MultiWrapper example, below is the DDVIDEOPORTCONNECT structure definition defined within DirectDraw:
struct DDVIDEOPORTCONNECT
{
DWORD dwSize;
DWORD dwPortWidth;
GUID guidTypeID;
DWORD dwFlags;
ULONG_PTR dwReserved1;
};
In the TDx_Library, this becomes a multiwrapper TComponent:
class TDDVideoPortConnect : public TComponent
{
// properties:
__property dword Size[ dword pArrayIndex ];
__property dword PortWidth[ dword pArrayIndex ];
__property GUID TypeID[ dword pArrayIndex ];
__property dword Flags[ dword pArrayIndex ];
__property dword SizeAll;
__property dword ArraySize;
__property HRESULT ErrorValue;
__property DDVIDEOPORTCONNECT* Internal_DDCOLORKEY_Ptr[ dword pArrayIndex ];
__property AnsiString Flags_Strings[ dword pArrayIndex ];
// methods:
void __fastcall Clear( dword pArrayIndex );
void __fastcall ClearAll();
void __fastcall Internal_DDVIDEOPORTCONNECT_Update();
// events:
__property TDx_Error OnError();
// internals:
DDVIDEOPORTCONNECT* fDDVIDEOPORTCONNECT;
};
See the 'pArrayIndex' parameter everywhere?
A MultiWrapper maintains a dynamic array of structures, in this case an array of DDVIDEOPORTCONNECT structures.
The 'pArrayIndex' parameter is used to access the data inside a particular structure.
As an example :-
void __fastcall TForm1::Button1Click( TObject* Sender )
{
// get number of video port connections
dword port_id = 0;
dword num_connections = 0;
Dx_DrawVideoPortContainer1->GetVideoPortConnectInfo( port_id, &num_connections, NULL );
// tell the TDDVideoPortConnect MultiWrapper to reallocate storage to handle 'num_connections' DDVIDEOPORTCONNECT structures.
DDVideoPortConnect1->ArraySize = num_connections;
// retrieve video port connection information
Dx_DrawVideoPortContainer1->GetVideoPortConnectInfo( port_id, &num_connections, DDVideoPortConnect1 );
// display results
for (int i=0;i ShowMessage( "#" + IntToStr(i) + ": " + DDVideoPortConnect1->Flags_Strings[i] );
}
INTERFACE WRAPPERS
Top
Next
Prev
An "Interface Wrapper" component wraps an entire DirectX COM (Component Object Model) interface, such as
IDirectDraw7, IDirectDrawSurface7, IDirectSound, etc.
All functions normally associated with the COM interface have been translated to work inside the wrapper
as standard BCB-style component methods, with BCB-style parameters, automatic parameter checking,
automatic error checking and redirection to the component's OnError() event, and so on.
Basically, instead of having a COM interface with functions, you now have a BCB component with simplified VCL methods.
Parameters that "must be" a given value, are no longer required to be passed to the method,
and parameters that are not actually used do not need to be passed to the method.
Methods return true if successful or false on failure: the automatic error handling removes the
requirement to check each method return result for errors. If you want to check the error value
immediately after calling a function, simply check the components 'ErrorValue' property.
As an example, take a look at IDirectDraw7::EnumDisplayModes(), in it's COM format :-
HRESULT EnumDisplayModes( DWORD dwFlags, LPDDSURFACEDESC2 lpDDSurfaceDesc2, LPVOID lpContext, LPDDENUMMODESCALLBACK2 lpEnumModesCallback );
Compare it to TDx_Draw::EnumDisplayModes(), the TDx_Library equivalent :-
bool __fastcall TDx_Draw::EnumDisplayModes( dword Flags, TDDSurfaceDesc* SurfaceDesc, void* Context );
Note the missing "Callback"? You don't have to implement callbacks.
The TDx_Draw::EnumDisplayModes() method automatically calls the TDx_Draw::OnEnumDisplayModes() callback event instead!
Note also the direct translation of parameters from DirectX conventions to VCL conventions.
Another example, TDx_DrawSurface::Blt() :-
HRESULT Blt( LPRECT lpDestRect, LPDIRECTDRAWSURFACE7 lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx );
Becomes :-
virtual bool __fastcall Blt( TRect* pDestRect, TDx_DrawSurface* pSrcSurface, TRect* pSrcRect, dword pFlags, TDDBltFX* pBltFx );
This time, note the translation of the LPRECT to TRect?
Same everywhere. Whatever can be translated has been translated.
Each Interface Wrapper automatically creates and destroys it's own interface, saving much tedious programming.
eg:
void __fastcall TForm1::FormCreate( TObject* Sender )
{
if (Dx_Draw1->Create( NULL ))
ShowMessage( "DirectDraw7 interface created successfully" );
else
ShowMessage( "Could not create DirectDraw7 interface" );
}
void __fastcall TForm1::FormDestroy( TObject* Sender )
{
if (Dx_Draw1->Created)
if (Dx_Draw1->Destroy())
ShowMessage( "DirectDraw7 interface destroyed successfully" );
else
ShowMessage( "Could not destroy DirectDraw7 interface" );
}
Upon successful creation of the COM interface, an interface wrapper calls it's OnCreate() event.
Midway through destruction, just prior to destroying the COM interface, an interface wrapper calls it's OnDestroy() event.
eg:
void __fastcall TForm1::FormCreate( TObject* Sender )
{
Dx_Draw1->Create( NULL );
}
void __fastcall TForm1::FormDestroy( TObject* Sender )
{
if (Dx_Draw1->Created) Dx_Draw1->Destroy();
}
void __fastcall TForm1::Dx_Draw1Create( TObject* Sender )
{
ShowMessage( "DirectDraw7 interface created successfully" );
}
void __fastcall TForm1::Dx_Draw1Destroy( TObject* Sender )
{
ShowMessage( "DirectDraw7 interface is being destroyed" );
}
The OnCreate() and OnDestroy() events are fantastic for automatically cascading related data elements.
eg:
void __fastcall TForm1::FormCreate( TObject* Sender )
{
Dx_Draw1->Create( NULL );
}
void __fastcall TForm1::FormDestroy( TObject* Sender )
{
if (Dx_Draw1->Created) Dx_Draw1->Destroy();
}
void __fastcall TForm1::Dx_Draw1Create( TObject* Sender )
{
ShowMessage( "DirectDraw7 interface created successfully" );
Dx_DrawSurface1->Create( DDSurfaceDesc1, Dx_Draw1 );
}
void __fastcall TForm1::Dx_Draw1Destroy( TObject* Sender )
{
ShowMessage( "DirectDraw7 interface is being destroyed" );
if (Dx_DrawSurface1->Created) Dx_DrawSurface1->Destroy();
}
void __fastcall TForm1::Dx_DrawSurface1Create( TObject* Sender )
{
ShowMessage( "DirectDrawSurface interface created successfully" );
Dx_DrawSurface1->GetCaps( DDSCaps1 );
}
void __fastcall TForm1::Dx_DrawSurface1Destroy( TObject* Sender )
{
ShowMessage( "DirectDrawSurface interface is being destroyed" );
DDSCaps1->Clear();
}
Automatic error handling is easy:
void __fastcall TForm1::Dx_Draw1Error( TObject* Sender, AnsiString Function, AnsiString Error, AnsiString ErrorMessage )
{
ShowMessage("An error occurred in the Dx_Draw1 component:\n\
The Function: "+Function+"\nThe Error: "+Error+"\nThe Error Message: "+ErrorMessage );
}
DirectX Callbacks can be painful to implement within BCB.
Within the TDx_Library, all callbacks are translated automatically and become easy-to-use BCB events.
For example, the TDx_Draw::EnumDisplayModes() method automatically calls the TDx_Draw::OnEnumDisplayModes() event,
the TDx_Draw::DDEnumerate() method automatically calls the TDx_Draw::OnDDEnumerate() event, etc.
Below are examples of callback event's :-
void __fastcall TForm1::Dx_Draw1DDEnumerate(TObject *Sender, GUID *Guid, AnsiString DriverDescription,
AnsiString DriverName, void *Context, HMONITOR HMonitor, bool &Finished)
{
ShowMessage( "Found a DirectX Device:\n\
Driver Name:"+DriverName+"\nDriver Description: "+DriverDescription );
}
void __fastcall TForm1::Dx_Draw1EnumDisplayModes(TObject *Sender, TDDSurfaceDesc *SurfaceDesc, void *Context,
bool &Finished)
{
ShowMessage( "Found a Display Mode: "+
IntToStr( (int)SurfaceDesc->Width) + "x" +
IntToStr( (int)SurfaceDesc->Height) + "x" +
IntToStr( (int)SurfaceDesc->PixelFormat->RGBBitCount) );
}
COMPONENT LIST
Top
Next
Prev
This is a list of the different component types for currently released libraries :-
For detailed information on each component, try the component reference.
TDx_Draw_Library
TDDBltFX - Wrapper
TDDCaps - Wrapper
TDDColorControl - Wrapper
TDDColorKey - Wrapper
TDDDeviceIndentifier - Wrapper
TDDGammaRamp - Wrapper
TDDOverlayFX - Wrapper
TDDPixelFormat - MultiWrapper
TDDSCaps - Wrapper
TDDSurfaceDesc - Wrapper
TDDVideoPortBandwidth - Wrapper
TDDVideoPortCaps - Wrapper
TDDVideoPortConnect - MultiWrapper
TDDVideoPortDesc - Wrapper
TDDVideoPortInfo - Wrapper
TDDVideoPortStatus - Wrapper
TDx_Draw - Interface
TDx_DrawClipper - Interface
TDx_DrawColorControl - Interface
TDx_DrawGammaControl - Interface
TDx_DrawPalette - Interface
TDx_DrawSurface - Interface
TDx_DrawVideoPort - Interface
TDx_DrawVideoPortContainer - Interface
TDx_Sound_Library
TDS3DBuffer - Wrapper
TDS3DListener - Wrapper
TDSBCaps - Wrapper
TDSBPositionNotify - MultiWrapper
TDSBufferDesc - Wrapper
TDSCBCaps - Wrapper
TDSCBufferDesc - Wrapper
TDSCCaps - Wrapper
TDSCaps - Wrapper
TDx_Sound - Interface
TDx_Sound3DBuffer - Interface
TDx_Sound3DListener - Interface
TDx_SoundBuffer - Interface
TDx_SoundCapture - Interface
TDx_SoundCaptureBuffer - Interface
TDx_SoundKsPropertySet - Interface
TDx_SoundNotify - Interface -> Hidden Thread not in DirectX
TDx_Input_Library
TDICondition - MultiWrapper
TDIConstantForce - Wrapper
TDICustomForce - Wrapper
TDIDataFormat - Wrapper
TDIDevCaps - Wrapper
TDIDeviceInstance - Wrapper
TDIDeviceObjectData - MultiWrapper
TDIDeviceObjectInstance - Wrapper
TDIEffectEscape - Wrapper
TDIEffect - Wrapper
TDIEffectInfo - Wrapper
TDIEnvelope - Wrapper
TDIFileEffect - MultiWrapper
TDIJoyState - Wrapper
TDIJoyState2 - Wrapper
TDIKeyboardState - Wrapper -> not in DirectX
TDIMouseState - Wrapper
TDIMouseState2 - Wrapper
TDIObjectDataFormat - MultiWrapper
TDIPeriodic - Wrapper
TDIPropDWORD - Wrapper
TDIPropGuidAndPath - Wrapper
TDIPropHeader - Wrapper
TDIPropRange - Wrapper
TDIPropString - Wrapper
TDIRampForce - Wrapper
TDx_Input - Interface
TDx_InputDevice - Interface -> Hidden Thread not in DirectX
TDx_InputEffect - Interface
TDx_Play_Library
TDPAccountDesc - Wrapper
TDApplicationDesc - Wrapper
TDPCaps - Wrapper
TDPChat - Wrapper
TDPComPortAddress - Wrapper
TDPCompoundAddressElement - MultiWrapper
TDPCredentials - Wrapper
TDPLAppInfo - Wrapper
TDPLConnection - Wrapper
TDPName - Wrapper
TDPSecurityDesc - Wrapper
TDPSessionDesc - Wrapper
TDx_Play - Interface -> Hidden Thread not in DirectX
TDx_PlayLobby - Interface -> Hidden Thread not in DirectX
TDx_3DI_Library
TD3DClipStatus - Wrapper
TD3DColorValue - Wrapper
TD3DDP_PtrStride - MultiWrapper
TD3DDevInfo_TextureManager - Wrapper
TD3DDevInfo_Texturing - Wrapper
TD3DDeviceDesc - Wrapper
TD3DDrawPrimitiveStridedData - MultiWrapper
TD3DLVertex - MultiWrapper
TD3DLight - Wrapper
TD3DLightingCaps - Wrapper
TD3DLinePattern - Wrapper
TD3DMaterial - Wrapper
TD3DMatrix - Wrapper
TD3DPrimCaps - Wrapper
TD3DRect - MultiWrapper
TD3DTLVertex - MultiWrapper
TD3DVector - MultiWrapper
TD3DVertex - MultiWrapper
TD3DVertexBufferDesc - Wrapper
TD3DViewport - Wrapper
TDx_3D - Interface
TDx_3DDevice - Interface
TDx_3DVertexBuffer - Interface
MORE INFORMATION
Top
Next
Prev
For more information, choose from the following links :-
|
|