// -------------------------------------------------------------------------- // ========================================================================== // File: TDx_InputDevice.CPP // Authors: BCB_Code_Generator v1.70, // Darren Dwyer (source code, documentation, demos, website), // Hugh Edwards (documentation, icons, website), // Brian Austin (some source code, documentation) // Description: This file contains the code for the TDx_InputDevice // Component // // "TDx_Input_Library v1.70" // (c) 2003 BCB-Tools.com Pty. Ltd., Sydney, Australia. // All Rights Reserved. // // Refer to the 'Licence.Txt' file for licencing & copyright information. // ========================================================================== // -------------------------------------------------------------------------- // #includes ... // -------------------------------------------------------------------------- #include #pragma hdrstop // -------------------------------------------------------------------------- #include "TDx_InputDevice.H" // -------------------------------------------------------------------------- // external classes used by the TDx_InputDevice component. #include "TDx_Input.H" #include "TDIMouseState.H" #include "TDIMouseState2.H" #include "TDIJoyState.H" #include "TDIJoyState2.H" #include "TDIKeyboardState.H" #include "TDIDataFormat.H" // -------------------------------------------------------------------------- // external classes used by TDx_InputDevice methods. #include "TDIEffect.H" #include "TDx_InputEffect.H" #include "TDIEffEscape.H" #include "TDIDevCaps.H" #include "TDIDeviceObjectData.H" #include "TDIDeviceInstance.H" #include "TDIEffectInfo.H" #include "TDIDeviceObjectInstance.H" #include "TDIPropHeader.H" #include "TDIPropDWORD.H" #include "TDIPropGuidAndPath.H" #include "TDIPropRange.H" #include "TDIPropString.H" #include "TDIFileEffect.H" // -------------------------------------------------------------------------- #pragma link "TDx_Library_Defns" #pragma link "TDx_Library_Functions" #pragma link "TDx_Input_Library_Defns" #pragma link "TDx_Input_Library_Functions" // -------------------------------------------------------------------------- // Object Registration... // -------------------------------------------------------------------------- #if (__BORLANDC__ >= 0x0530) // BCB Version 3+ #pragma package(smart_init) #endif // -------------------------------------------------------------------------- static inline void ValidCtrCheck(TDx_InputDevice*) { new TDx_InputDevice(NULL); } // -------------------------------------------------------------------------- namespace Tdx_inputdevice { #if (__BORLANDC__ >= 0x0530) // BCB Version 3+ void __fastcall PACKAGE Register() #else void __fastcall Register() #endif { TComponentClass classes[1] = {__classid(TDx_InputDevice)}; RegisterComponents("TDx_Input", classes, 0); } } // -------------------------------------------------------------------------- // Global Variables used internally by the TDx_InputDevice component. // -------------------------------------------------------------------------- static TDx_InputDevice* TDx_InputDevice_ThreadParent = NULL; // -------------------------------------------------------------------------- class TDx_InputDevice_ThreadClass : public TThread { public: __property bool HandlesModified = {write=fHandlesModified, default=true}; void __fastcall DoNothing() {} // minor delay due to method call void __fastcall Pause() // called only by other threads, never this thread { while (fRebuildingHandles) DoNothing(); SetEvent( fPauseEvent ); } void __fastcall Restart() // called only by other threads, never this thread { while (fRebuildingHandles) DoNothing(); SetEvent( fRestartEvent ); } void __fastcall TerminateImmediately() // called only by other threads, never this thread { while (fRebuildingHandles) DoNothing(); SetEvent( fTerminateEvent ); } void __fastcall RebuildHandles(); __fastcall TDx_InputDevice_ThreadClass(); virtual __fastcall ~TDx_InputDevice_ThreadClass(); protected: void __fastcall Execute(); void __fastcall Translate(); private: HANDLE* fHandles; TDx_InputDevice** fHandleOwners; int fNumHandles; int fEventNum; bool fHandlesModified; bool fRebuildingHandles; HANDLE fPauseEvent; HANDLE fRestartEvent; HANDLE fTerminateEvent; int fPauseIndex; int fRestartIndex; int fTerminateIndex; }; //--------------------------------------------------------------------------- static TList* TDx_InputDevice_ComponentList = NULL; static TDx_InputDevice_ThreadClass* TDx_InputDevice_Thread = NULL; // -------------------------------------------------------------------------- // Global Functions used internally by the TDx_InputDevice component. // -------------------------------------------------------------------------- __fastcall TDx_InputDevice_ThreadClass::TDx_InputDevice_ThreadClass() : TThread(true) { fHandles = NULL; fNumHandles = 0; fEventNum = 0; fPauseEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); fPauseIndex = -1; fRestartEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); fRestartIndex = -1; fTerminateEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); fTerminateIndex = -1; fHandlesModified = true; fRebuildingHandles = false; } //--------------------------------------------------------------------------- __fastcall TDx_InputDevice_ThreadClass::~TDx_InputDevice_ThreadClass() { if (fHandles) { delete[] fHandles; fHandles = NULL; fNumHandles = 0; } if (fTerminateEvent) { CloseHandle( fTerminateEvent ); fTerminateEvent = NULL; } if (fRestartEvent) { CloseHandle( fRestartEvent ); fRestartEvent = NULL; } if (fPauseEvent) { CloseHandle( fPauseEvent ); fPauseEvent = NULL; } } //--------------------------------------------------------------------------- void __fastcall TDx_InputDevice_ThreadClass::Execute() { FreeOnTerminate = true; // wait for events while (true) { // rebuild handles iff required if (fHandlesModified) { fRebuildingHandles = true; RebuildHandles(); fHandlesModified = false; // do not change the order of these 2 bools fRebuildingHandles = false; // because other threads might be waiting for -this- result before changing ^one } // wait for notifications + pause, restart, terminate events fEventNum = WaitForMultipleObjects( fNumHandles+3, fHandles, FALSE, INFINITE ); // if for some reason the handles were invalid, re-try if (fEventNum==WAIT_FAILED) { fHandlesModified = true; // force a rebuild of the handles continue; } // modify the result fEventNum -= WAIT_OBJECT_0; // if it's a pause, wait for a resume or a terminate if (fEventNum == fPauseIndex) { // wait for restart / terminate event fEventNum = WaitForMultipleObjects( 2, &fHandles[fRestartIndex], FALSE, INFINITE ); } // if it's a restart, simply restart if (fEventNum == fRestartIndex) { continue; } // if it's a terminate event, exit immediately if (fEventNum == fTerminateIndex) { break; } // otherwise, the event is a notification event, send it to the user if (fEventNum < fNumHandles) { Synchronize(Translate); } } // finished } //--------------------------------------------------------------------------- void __fastcall TDx_InputDevice_ThreadClass::RebuildHandles() { if (fHandles) { delete[] fHandles; fHandles = NULL; fNumHandles = 0; } if (fHandleOwners) { delete[] fHandleOwners; fHandleOwners = NULL; } // determine the number of handles that need to be added int num_handles = 0; for (int i=0;iCount;i++) { TDx_InputDevice* device = (TDx_InputDevice*) TDx_InputDevice_ComponentList->Items[i]; if (device!=NULL) if (device->Created) if (device->EventHandle!=NULL) num_handles += 1; } // allocate storage for handles and something to tell us who the handle refers to fHandles = new HANDLE [num_handles+3]; if (!fHandles) return; fHandleOwners = new TDx_InputDevice* [num_handles+3]; if (!fHandleOwners) { delete[] fHandles; fHandles = NULL; return; } fNumHandles = num_handles; // add notification events to internal storage int pos = 0; for (int i=0;iCount;i++) { TDx_InputDevice* device = (TDx_InputDevice*) TDx_InputDevice_ComponentList->Items[i]; if (device!=NULL) if (device->Created) if (device->EventHandle!=NULL) { fHandles[pos] = device->EventHandle; fHandleOwners[pos] = device; pos++; } } // add pause, restart, terminate events fPauseIndex = fNumHandles; fHandles[fPauseIndex] = fPauseEvent; fRestartIndex = fNumHandles+1; fHandles[fRestartIndex] = fRestartEvent; fTerminateIndex = fNumHandles+2; fHandles[fTerminateIndex] = fTerminateEvent; } //--------------------------------------------------------------------------- void __fastcall TDx_InputDevice_ThreadClass::Translate() { // if the handles were modified during the synchronize, abort immediately if (fHandlesModified) { return; } // send it to the relevant BCB event handler try { TDx_InputDevice* device = fHandleOwners[fEventNum]; if (device->OnDeviceStateChange) device->OnDeviceStateChange( device ); } // absorb anything extraordinary catch (...) {} } // -------------------------------------------------------------------------- // Extra code for Callback Handling // -------------------------------------------------------------------------- TDx_InputDevice* TDx_InputDevice_OnEnumCreatedEffectObjectsOwner = NULL; TDx_InputDevice* TDx_InputDevice_OnEnumEffectsOwner = NULL; TDx_InputDevice* TDx_InputDevice_OnEnumEffectsInFileOwner = NULL; TDx_InputDevice* TDx_InputDevice_OnEnumObjectsOwner = NULL; // -------------------------------------------------------------------------- // Constructor: TDx_InputDevice::TDx_InputDevice() // Description: The default constructor for the TDx_InputDevice object. // -------------------------------------------------------------------------- __fastcall TDx_InputDevice::TDx_InputDevice(TComponent* Owner) : TComponent(Owner) { fCreated = false; fErrorValue = DI_OK; fEventHandle = NULL; fLastDataFormat = NULL; // only create the thread at runtime. // if we're not currently running inside the BCB ide... bool inside_ide = false; if (Screen) if (Screen->ActiveForm) if (Screen->ActiveForm->Designer) inside_ide = true; if (!inside_ide) { if (TDx_InputDevice_ThreadParent==NULL) { TDx_InputDevice_ComponentList = new TList(); if (TDx_InputDevice_ComponentList) { TDx_InputDevice_Thread = new TDx_InputDevice_ThreadClass(); if (TDx_InputDevice_Thread) { TDx_InputDevice_ThreadParent=this; TDx_InputDevice_Thread->Resume(); // set the thread running... } else { delete TDx_InputDevice_ComponentList; TDx_InputDevice_ComponentList = NULL; TDx_InputDevice_ThreadParent = NULL; } } } } } // -------------------------------------------------------------------------- // Destructor: TDx_InputDevice::~TDx_InputDevice() // Description: The destructor for the TDx_InputDevice object. // -------------------------------------------------------------------------- __fastcall TDx_InputDevice::~TDx_InputDevice() { // destroy internals if (Created) Destroy(); // destroy the thread iff required if (TDx_InputDevice_Thread!=NULL) if (TDx_InputDevice_ThreadParent==this) { TDx_InputDevice_Thread->Pause(); // remove from list if (TDx_InputDevice_ComponentList) if (TDx_InputDevice_ComponentList->IndexOf(this)!=-1) TDx_InputDevice_ComponentList->Delete(TDx_InputDevice_ComponentList->IndexOf(this)); // if there are any other components still alive, migrate the parent bool migrated = false; for (int i=0;iCount;i++) if (TDx_InputDevice_ComponentList->Items[i]!=NULL) { TDx_InputDevice_ThreadParent = (TDx_InputDevice*) TDx_InputDevice_ComponentList->Items[i]; migrated = true; break; } // if could not migrate, destroy the thread and the component list if (!migrated) { TDx_InputDevice_Thread->TerminateImmediately(); TDx_InputDevice_Thread = NULL; delete TDx_InputDevice_ComponentList; TDx_InputDevice_ComponentList = NULL; TDx_InputDevice_ThreadParent = NULL; } else // restart the thread with the new parent. { TDx_InputDevice_Thread->HandlesModified = true; TDx_InputDevice_Thread->Restart(); } } } // -------------------------------------------------------------------------- // Property: Created // Description: The Created property is true if the internal // LPDIRECTINPUTDEVICE7 used in this component has been // successfully created, otherwise Created is false. // // To create the internal LPDIRECTINPUTDEVICE7, call the // TDx_InputDevice::Create() method. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::FGetCreated() { return fCreated; } // -------------------------------------------------------------------------- void __fastcall TDx_InputDevice::FSetCreated( bool pCreated ) { fCreated = (pCreated && (fLPDIRECTINPUTDEVICE7==NULL)); } // -------------------------------------------------------------------------- // Property: ErrorValue // Description: The ErrorValue property contains the last error value // returned from a call to a TDx_InputDevice method or // fget/fset. eg. DI_OK or DDERR_SURFACELOST or TDX_ERROR // -------------------------------------------------------------------------- HRESULT __fastcall TDx_InputDevice::FGetErrorValue() { return fErrorValue; } // -------------------------------------------------------------------------- void __fastcall TDx_InputDevice::FSetErrorValue( HRESULT pErrorValue ) { fErrorValue = pErrorValue; } // -------------------------------------------------------------------------- // Property: EventHandle // Description: The EventHandle property is used internally to store the // event assigned to the device. // -------------------------------------------------------------------------- HANDLE __fastcall TDx_InputDevice::FGetEventHandle() { return fEventHandle; } // -------------------------------------------------------------------------- // Property: LastDataFormat // Description: The LastDataFormat property is used internally to store the // data format last used within the // TDx_InputDevice::SetDataFormat() method. // -------------------------------------------------------------------------- TDIData* __fastcall TDx_InputDevice::FGetLastDataFormat() { return fLastDataFormat; } // -------------------------------------------------------------------------- // Method: Acquire() // Description: The Acquire() method will obtain access to the input device. // // A data format must be set using // TDx_InputDevice::SetDataFormat() before the device can be // aquired. // Devices must be acquired before // TDx_InputDevice::GetDeviceState() or // TDx_InputDevice::GetDeviceData() can be used. // // A device is either acquired or unaquired, thus calling // Acquire() multiple times and then calling // TDx_InputDevice::UnAquire() once still results in the device // being completely unacquired. // // You will need to call TDx_InputDevice::SetCooperativeLevel() // before calling this method. // // Error values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // DIERR_OTHERAPPHASPRIO // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::Acquire() { // Original Function Definition // HRESULT Acquire(); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Acquire()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->Acquire( ); // Handle any Known Results if ((fErrorValue!=DI_OK) && (fErrorValue!=S_FALSE)) { // Failure. if (FOnError) FOnError( this, Name+"::Acquire()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Create() // Description: The Create() method is used to automatically create the // internal LPDIRECTINPUTDEVICE7 interface used in the // TDx_InputDevice component and must be called before any // methods of the TDx_InputDevice component will function. // Params: pGuid - // The pGuid parameter is used to define what type of device to // create. System GUIDs for the mouse and keyboard are: // GUID_SysKeyboard // GUID_SysMouse // GUIDs for other devices are obtained by calling // TDx_Input::EnumDevices() // pInput - // The pInput parameter references a TDx_Input Object that has // been previously created. The TDx_Input::CreateDevice method // is called to create the InputDevice, these two methods are // identical in function. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::Create( GUID pGuid, TDx_Input* pInput ) { // if the component internals have already been created, exit if (fCreated) { if (FOnError) FOnError( this, Name+"::Create()", "TDX_ALREADYCREATED", "The "+Name+"::Create() method was called when the component has already been created successfully." ); return false; } // check params for accuracy if (pInput==NULL) { if (FOnError) FOnError( this, Name+"::Create()", "TDX_BADPARAMS", "The 'pInput' parameter must point to an existing TDx_Input component and cannot be NULL." ); return false; } // code that creates the internal IDirectInputDevice interface any error will be caught by the pInput object. if (pInput->CreateDevice(pGuid,this)) { fCreated = true; if (FOnCreate) FOnCreate(this); } // return true if created return fCreated; } // -------------------------------------------------------------------------- // Method: CreateEffect() // Description: The CreateEffect() method will create and initialize an // effect instance. // // A return value of S_OK will be generated if the device is not // acquired in exclusive mode. This indicates that the effect // has been created and its parameters updated, but it may not // have been downloaded to the device. // // Error values that can be generated are: // // DIERR_DEVICENOTREG // DIERR_DEVICEFULL // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pRefGuid - // The RefGuid parameter identifies the effect being created. // // One of the predefined effects below or a GUID obtained from // TDx_InputDevice::EnumEffects() can be used. // // GUID_ConstantForce // GUID_RampForce // // Periodic: // GUID_Square // GUID_Sine // GUID_Triangle // GUID_SawtoothUp // GUID_SawtoothDown // // Conditions: // GUID_Spring // GUID_Damper // GUID_Inertia // GUID_Friction // // User Defined: // GUID_CustomForce // pEffectData - // The EffectData parameter references a TDIEffect component // holding the properties of the effect being created. // // Set this property to NULL to create a blank effect object to // be set later up using TDx_InputEffect::SetParameters(). // pNewEffect - // The NewEffect parameter will reference the new // TDx_InputEffect interface if the method returns successfully. // -------------------------------------------------------------------------- HRESULT __fastcall TDx_InputDevice::CreateEffect( REFGUID pRefGuid, TDIEffect* pEffectData, TDx_InputEffect* pNewEffect ) { // Original Function Definition // HRESULT CreateEffect( // REFGUID rguid, // LPCDIEFFECT lpeff, // LPDIRECTINPUTEFFECT* ppdeff, // LPUNKNOWN punkOuter // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::CreateEffect()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pNewEffect==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::CreateEffect()", "TDX_BADPARAMS", "'pNewEffect' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->CreateEffect( pRefGuid, (pEffectData==NULL) ? NULL : pEffectData->Internal_DIEFFECT_Ptr, pNewEffect->Internal_LPDIRECTINPUTEFFECT_Ptr, NULL ); // Translate Data returned from Function if (pEffectData!=NULL) pEffectData->Internal_DIEFFECT_Update(); pNewEffect->Internal_LPDIRECTINPUTEFFECT_Update(); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::CreateEffect()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return fErrorValue; } // Success! return fErrorValue; } // -------------------------------------------------------------------------- // Method: Destroy() // Description: The Destroy() method is used to automatically destroy the // internal LPDIRECTINPUTDEVICE7 interface used in the // TDx_InputDevice component and should be called when the // internal interface is no longer required. // // Note: This method is called by the component's destructor. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::Destroy() { // if the component internals are not already created, exit if (!fCreated) { if (FOnError) FOnError( this, Name+"::Destroy()", "TDX_NOTCREATED", "The "+Name+"::Destroy() method was called before being created successfully." ); return false; } // pause existing thread if (TDx_InputDevice_Thread) TDx_InputDevice_Thread->Pause(); // make sure notifications are Disabled if (fEventHandle!=NULL) { // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->SetEventNotification( NULL ); // delete the event handle CloseHandle(fEventHandle); fEventHandle = NULL; } // destroy the internal interface try { if (FOnDestroy) FOnDestroy(this); } catch (...) { fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::Destroy()", "TDX_ERROR", "An exception has occurred within "+Name+"::OnDestroy()" ); } try { if (fLPDIRECTINPUTDEVICE!=NULL) fLPDIRECTINPUTDEVICE->Release(); } catch (...) { fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::Destroy()", "TDX_ERROR", "An exception has occurred within LPDIRECTINPUTDEVICE->Release(). Check that you are destroying all components in reverse order of creation." ); } // successful or unsuccessful destruction, continue regardless fLPDIRECTINPUTDEVICE = NULL; fCreated = false; // remove from list if (TDx_InputDevice_ComponentList) if (TDx_InputDevice_ComponentList->IndexOf(this)!=-1) TDx_InputDevice_ComponentList->Delete(TDx_InputDevice_ComponentList->IndexOf(this)); // restart the thread if (TDx_InputDevice_Thread) { TDx_InputDevice_Thread->HandlesModified = true; TDx_InputDevice_Thread->Restart(); } // success! return true; } // -------------------------------------------------------------------------- // Method: EnumCreatedEffectObjects() // Description: The EnumCreatedEffectObjects() method will enumerate effects // currently created for this device by // TDx_InputDevice::CreateEffect(). // // Creating or destroying effects while the enumeration is in // progress may result in unpredictable results, but the // callback function can safely release effects passed to it. // // Error values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pReferenceData - // The ReferenceData parameter defines context or reference data // to be passed to the callback function each time it is called. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::EnumCreatedEffectObjects( void* pReferenceData ) { // Original Function Definition // HRESULT EnumCreatedEffectObjects( // LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, // LPVOID pvRef, // DWORD fl // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::EnumCreatedEffectObjects()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function TDx_InputDevice_OnEnumCreatedEffectObjectsOwner = this; fErrorValue = fLPDIRECTINPUTDEVICE7->EnumCreatedEffectObjects( Internal_EnumCreatedEffectObjectsCallback, (LPVOID) pReferenceData, 0 ); TDx_InputDevice_OnEnumCreatedEffectObjectsOwner = NULL; // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::EnumCreatedEffectObjects()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: EnumEffects() // Description: The EnumEffects() method will enumerate the effects supported // by the device's force feedback system. // // The returned GUID's may represent predefined or device // specific effects. // // General effect information can be found in the EffectType // parameter, but to exploit a device specific effect to the // fullest, consult the documentation provided by the // manufacturer. // // Error values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pReferenceData - // The ReferenceData parameter references an application defined // 32 bit value to be passed to the callback function for each // enumeration. // pEffectType - // The EffectType parameter defines flags indicating which // effect types should be enumerated. // The described effect applies when the flag is set. // Flags: // DIEFT_ALL - // All effects are to be enumerated, regardless of type. // DIEFT_CONDITION - // Only conditions should be enumerated. // DIEFT_CONSTANTFORCE - // Only constant force effects should be enumerated. // DIEFT_CUSTOMFORCE - // Only custom forces should be enumerated. // DIEFT_HARDWARE - // Only hardware specific effects should be enumerated. // DIEFT_PERIODIC - // Only periodic effects should be enumerated. // DIEFT_RAMPFORCE - // Only ramp force effects should be enumerated. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::EnumEffects( void* pReferenceData, dword pEffectType ) { // Original Function Definition // HRESULT EnumEffects( // LPDIENUMEFFECTSCALLBACK lpCallback, // LPVOID pvRef, // DWORD dwEffectType // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::EnumEffects()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function TDx_InputDevice_OnEnumEffectsOwner = this; fErrorValue = fLPDIRECTINPUTDEVICE7->EnumEffects( Internal_EnumEffectsCallback, (LPVOID) pReferenceData, (DWORD) pEffectType ); TDx_InputDevice_OnEnumEffectsOwner = NULL; // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::EnumEffects()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: EnumEffectsInFile() // Description: The EnumEffectsInFile() method will enumerate effects stored // in a file by the Force Editor utility or another application // that utilizes the same file format. (RIFF) // // The Force Editor is included with the DirectX sdk and can // usually be found at (SDK root)\Bin\Dxutils\Fedit.exe or under // DirectX 7->DX Tools on your start bar. // // When enumeration is halted by the callback function, the // return result is still DI_OK. // // Error values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pFileName - // The FileName parameter defines the name of the RIFF file. // pReferenceData - // The ReferenceData parameter references an application defined // 32 bit value to be passed to the callback function for each // enumeration. // pFlags - // The Flags parameter defines flags indicating which effects to // include or modify while enumerating. // The described effect applies when the flag is set. // Flags: // DIFEF_DEFAULT - // This flag is equivilent to setting the parameter to 0. // DIFEF_INCLUDENONSTANDARD - // Effect types that are undefined by DirectInput should // also be enumerated. // DIFEF_MODIFYIFNEEDED - // Modify the effects being enumerated so that they can be // played on this device. // // Setting this flag causes the properties of the // TDIEffect component referenced by the // TDIFileEffect::Effect in the callback function to be // modified. // // For example : An attempt to play an effect authored for // a two axis device on a single axis device will fail // unless this flag was set when retrieving the effect // from the file. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::EnumEffectsInFile( AnsiString pFileName, void* pReferenceData, dword pFlags ) { // Original Function Definition // HRESULT EnumEffectsInFile( // LPCSTR lpszFileName, // LPENUMEFFECTSINFILECALLBACK pec, // LPVOID pvRef, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::EnumEffectsInFile()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Translate Parameters before calling Original Function AnsiString TempFileName = pFileName; // Call Original Function TDx_InputDevice_OnEnumEffectsInFileOwner = this; fErrorValue = fLPDIRECTINPUTDEVICE7->EnumEffectsInFile( (LPCSTR) TempFileName.c_str(), Internal_EnumEffectsInFileCallback, (LPVOID) pReferenceData, (DWORD) pFlags ); TDx_InputDevice_OnEnumEffectsInFileOwner = NULL; // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::EnumEffectsInFile()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: EnumObjects() // Description: The EnumObjects() method will enumerate the individual input // and force feedback objects of a device. // // Error values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pReferenceData - // The ReferenceData parameter defines context or reference data // to be passed to the callback function each time it is called. // pFlags - // The Flags parameter defines flags indicating which object // types are to be enumerated. // The described effect applies when the flag is set. // // Objects matching any of the flags set will be enumerated // unless DIDFT_FFACTUATOR or DIDFT_FFEFFECTTRIGGER is present, // in which case enumeration is limited to objects matching all // the set flags values. // Flags: // DIDFT_ABSAXIS - // Enumerate any object with an absolute axis. // DIDFT_ALL - // Enumerate all objects. // DIDFT_AXIS - // Enumerate any object with an absolute or relative axis. // DIDFT_BUTTON - // Enumerate any object with push or toggle buttons. // DIDFT_COLLECTION - // Enumerate HID link collections. // DIDFT_ENUMCOLLECTION(n) - // Enumerate objects that belong to HID link collection // number n. // DIDFT_FFACTUATOR - // Enumerate objects to which force-feedback may be // applied. // DIDFT_FFEFFECTTRIGGER - // Enumerate objects that can trigger force-feedback // effects. // DIDFT_NOCOLLECTION - // Enumerate objects that do not belong to any HID link // collection. // Objects falling into this category are those that have // TDIDeviceObjectInstance::CollectionNumber = 0. // DIDFT_NODATA - // Enumerate objects that do not generate data. // DIDFT_OUTPUT - // Enumerate objects to which data can be sent using // TDx_InputDevice::SendDeviceData(). // DIDFT_POV - // Enumerate point-of-view controllers. // DIDFT_PSHBUTTON - // Enumerate push buttons. // Push buttons is reported as down when pressed, and up // when released. // DIDFT_RELAXIS - // Enumerate objects with a relative axis. // DIDFT_TGLBUTTON - // Enumerate objects that are toggle buttons. // Toggle buttons are reported down when pressed, and // remain down until re-pressed. // DIDFT_VENDORDEFINED - // Enumerate objects of a type defined by the device // manufacturer. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::EnumObjects( void* pReferenceData, dword pFlags ) { // Original Function Definition // HRESULT EnumObjects( // LPDIENUMDEVICEOBJECTSCALLBACK lpCallback, // LPVOID pvRef, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::EnumObjects()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function TDx_InputDevice_OnEnumObjectsOwner = this; fErrorValue = fLPDIRECTINPUTDEVICE7->EnumObjects( Internal_EnumObjectsCallback, (LPVOID) pReferenceData, (DWORD) pFlags ); TDx_InputDevice_OnEnumObjectsOwner = NULL; // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::EnumObjects()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Escape() // Description: The Escape() method will send a hardware-specific command // directly to the device driver. // // TDIDeviceInstance::FFDriver should be checked against the // expected driver identifier to ensure the escape is sent to // the right driver. // // The driver documentation should list and describe the comands // that are valid for the driver. // // Error Values that can be generated are: // // DIERR_NOTINITIALIZED // DIERR_DEVICEFULL // Params: pEscape - // The EffectEscape parameter references a TDIEffEscape // component describing the command to be sent to the driver. // // On returning, the TDIEffEscape::OutBufferSize property will // define amount of data, in bytes, written to // TDIEffEscape::OutBuffer. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::Escape( TDIEffEscape* pEscape ) { // Original Function Definition // HRESULT Escape( // LPDIEFFESCAPE pesc // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Escape()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pEscape==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::Escape()", "TDX_BADPARAMS", "'pEscape' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->Escape( pEscape->Internal_DIEFFESCAPE_Ptr ); // Translate Data returned from Function pEscape->Internal_DIEFFESCAPE_Update(); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::Escape()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetCapabilities() // Description: The GetCapabilities() method will retrieve the cababilities // of this device. // // Error Values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pDevCaps - // The DevCaps parameter references a TIDevCaps component for // holding the device capabilities if this method returns // successfully. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::GetCapabilities( TDIDevCaps* pDevCaps ) { // Original Function Definition // HRESULT GetCapabilities( // LPDIDEVCAPS lpDIDevCaps // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetCapabilities()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pDevCaps==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetCapabilities()", "TDX_BADPARAMS", "'pDevCaps' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->GetCapabilities( pDevCaps->Internal_DIDEVCAPS_Ptr ); // Translate Data returned from Function pDevCaps->Internal_DIDEVCAPS_Update(); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetCapabilities()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetDeviceData() // Description: The GetDeviceData() method will retrieve buffered data that // the device is holding. // // The data format must be set with // TDx_InputDevice::SetDataFormat(), the buffer size must be set // with TDx_InputDevice::SetProperty() and the device acquired // with TDx_InputDevice::Acquire() before device data can be // obtained. // // To flush the buffer, set the DOD parameter to NULL and the // InOut parameter to INFINITE. // The number of items flushed will be returned in the InOut // parameter. // Setting the Flags parameter to DIGDD_PEEK will return the // number of items without flushing the buffer. // // Error Values that can be generated are: // // DIERR_INPUTLOST // DIERR_INVALIDPARAM // DIERR_NOTACQUIRED // DIERR_NOTBUFFERED // DIERR_NOTINITIALIZED // Params: pObjectData - // The ObjectData parameter defines the size, in bytes, of each // of the TDIDeviceObjectData components referenced by the DOD // parameter. // pDeviceObjectData - // The DeviceObjectData parameter references an array of // TDIDeviceDeviceObjectData components for holding the data // retrieved. // // Setting this parameter to NULL will discard the buffered data // while still allowing the other effects of the method call to // occur. // pInOut - // The InOut parameter initially defines the number of elements // in the DOD array and on return it holds the actual number of // elements retrieved. // pFlags - // The Flags parameter defines a flag indicating whether to // retain the data after if has been retrieved. // The described effect applies when the flag is set. // Flags: // DIGDD_PEEK - // Retrieved data will not be removed from the buffer and // thus the next TDx_InputDevice::GetDeviceData() call // will retrieve the same data. // // Data is usually removed from the buffer after // retrieval. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::GetDeviceData( dword pObjectData, TDIDeviceObjectData* pDeviceObjectData, dword* pInOut, dword pFlags ) { // Original Function Definition // HRESULT GetDeviceData( // DWORD cbObjectData, // LPDIDEVICEOBJECTDATA rgdod, // LPDWORD pdwInOut, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetDeviceData()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->GetDeviceData( (DWORD) pObjectData, (pDeviceObjectData==NULL) ? NULL : pDeviceObjectData->Internal_DIDEVICEOBJECTDATA_Ptr, (LPDWORD) pInOut, (DWORD) pFlags ); // Translate Data returned from Function if (pDeviceObjectData!=NULL) pDeviceObjectData->Internal_DIDEVICEOBJECTDATA_Update(); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetDeviceData()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetDeviceInfo() // Description: The GetDeviceInfo() method will obtain the device's identity // information. // // Error Values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pDeviceInstance - // The DeviceInstance parameter references a TDIDeviceInstance // component for holding the device identity information if the // method returns successfully. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::GetDeviceInfo( TDIDeviceInstance* pDeviceInstance ) { // Original Function Definition // HRESULT GetDeviceInfo( // LPDIDEVICEINSTANCE pdidi // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetDeviceInfo()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pDeviceInstance==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetDeviceInfo()", "TDX_BADPARAMS", "'pDeviceInstance' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->GetDeviceInfo( pDeviceInstance->Internal_DIDEVICEINSTANCE_Ptr ); // Translate Data returned from Function pDeviceInstance->Internal_DIDEVICEINSTANCE_Update(); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetDeviceInfo()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetDeviceState() // Description: The GetDeviceState() method will retrieve the current state // of the device. // // The cooperative level must be set with // TDx_InputDevice::SetCooperativeLevel(), the data format must // be set with TDx_InputDevice::SetDataFormat() and the device // acquired with TDx_InputDevice::Acquire() before the device // state can be obtained. // // Error values that can be generated are: // // DIERR_INPUTLOST // DIERR_INVALIDPARAM // DIERR_NOTACQUIRED // DIERR_NOTINITIALIZED // E_PENDING // Params: pState - // The State parameter references an object for holding the // current state of the device. // // Most of the time this parameter references a TDIMouseState, // TDIMouseState2, TDIKeyboardState, TDIJoyState or TDIJoystate2 // component for holding the state information of the predefined // data formats. // // Otherwise the format of the data will have been previously // established using TDx_InputDevice::SetDataFormat(). // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::GetDeviceState( TDIData* pState ) { // Original Function Definition // HRESULT GetDeviceState( // DWORD cbData, // LPVOID lpvData // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetDeviceState()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check that the SetDataFormat() method has been called if (fLastDataFormat == NULL) { if (FOnError) FOnError( this, Name+"::GetDeviceState()", "TDX_ERROR", "The TDx_InputDevice::SetDataFormat() needs to be called before the TDx_InputDevice::GetDeviceState() method will work." ); return false; } // Check Parameters for Accuracy if (pState == NULL) { if (FOnError) FOnError( this, Name+"::GetDeviceState()", "TDX_ERROR", "The 'pState' parameter must refer to an existing TDIDataFormat, TDIMouseState, TDIKeyboardState or TDIJoyState component and cannot be NULL."); return false; } // Check Parameters for Accuracy AnsiString class_name = pState->ClassType()->ClassName(); AnsiString original_class_name = fLastDataFormat->ClassType()->ClassName(); if (original_class_name != class_name) { if (FOnError) FOnError( this, Name+"::GetDeviceState()", "TDX_ERROR", "The 'pState' parameter must be the same type of class passed into the SetDataFormat() method." ); return false; } // Call Original Function if (class_name=="TDIMouseState") { TDIMouseState* state = (TDIMouseState*) pState; fErrorValue = fLPDIRECTINPUTDEVICE7->GetDeviceState( state->Size, (void*) state->Internal_DIMOUSESTATE_Ptr ); state->Internal_DIMOUSESTATE_Update(); } else if (class_name=="TDIMouseState2") { TDIMouseState2* state = (TDIMouseState2*) pState; fErrorValue = fLPDIRECTINPUTDEVICE7->GetDeviceState( state->Size, (void*) state->Internal_DIMOUSESTATE2_Ptr ); state->Internal_DIMOUSESTATE2_Update(); } else if (class_name=="TDIJoyState") { TDIJoyState* state = (TDIJoyState*) pState; fErrorValue = fLPDIRECTINPUTDEVICE7->GetDeviceState( state->Size, (void*) state->Internal_DIJOYSTATE_Ptr ); state->Internal_DIJOYSTATE_Update(); } else if (class_name=="TDIJoyState2") { TDIJoyState2* state = (TDIJoyState2*) pState; fErrorValue = fLPDIRECTINPUTDEVICE7->GetDeviceState( state->Size, (void*) state->Internal_DIJOYSTATE2_Ptr ); state->Internal_DIJOYSTATE2_Update(); } else if (class_name=="TDIKeyboardState") { TDIKeyboardState* state = (TDIKeyboardState*) pState; fErrorValue = fLPDIRECTINPUTDEVICE7->GetDeviceState( state->Size, (void*) state->Internal_DIKEYBOARDSTATE_Ptr ); state->Internal_DIKEYBOARDSTATE_Update(); } else if (class_name=="TDIDataFormat") { TDIDataFormat* state = (TDIDataFormat*) pState; fErrorValue = fLPDIRECTINPUTDEVICE7->GetDeviceState( state->Size, (void*) state->Internal_DIDATAFORMAT_Ptr); state->Internal_DIDATAFORMAT_Update(); } // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetDeviceState()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Finished! return true; } // -------------------------------------------------------------------------- // Method: GetEffectInfo() // Description: The GetEffectInfo() method will retrieve information about an // effect. // // Error values that can be generated are: // // DIERR_DEVICENOTREG // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pEffectInfo - // The EffectInfo parameter references a TDIEffectInfo component // for holding the effect information if the method returns // successfully. // pRefGuid - // The RefGuid parameter identifies the effect for which the // information is to be retrieved. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::GetEffectInfo( TDIEffectInfo* pEffectInfo, REFGUID pRefGuid ) { // Original Function Definition // HRESULT GetEffectInfo( // LPDIEFFECTINFO pdei, // REFGUID rguid // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetEffectInfo()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pEffectInfo==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetEffectInfo()", "TDX_BADPARAMS", "'pEffectInfo' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->GetEffectInfo( pEffectInfo->Internal_DIEFFECTINFO_Ptr, pRefGuid ); // Translate Data returned from Function pEffectInfo->Internal_DIEFFECTINFO_Update(); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetEffectInfo()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetForceFeedbackState() // Description: The GetForceFeedbackState() method will retrieve the current // state of the force feedback system of the device. // // The exclusive cooperative level is required for this method // to succeed. // // Error values that can be generated are: // // DIERR_INPUTLOST // DIERR_INVALIDPARAM // DIERR_NOTEXCLUSIVEACQUIRED // DIERR_NOTINITIALIZED // DIERR_UNSUPPORTED // Params: pOut - // The Out parameter defines flags describing the current force // feedback state. // The described effect applies when the flag is set. // Flags: // DIGFFS_ACTUATORSOFF - // The force feedback actuators of the device are // currently disabled. // DIGFFS_ACTUATORSON - // The force feedback actuators of the device are // currently enabled. // DIGFFS_DEVICELOST - // The device has unexpectedly failed and is currently in // an indeterminate state, the device must be either // unacquired and reacquired or have a DISFFC_RESET // command sent to it. // DIGFFS_EMPTY - // The device currently has no effects downloaded. // DIGFFS_PAUSED - // The device playback of all active effects has been // paused. // DIGFFS_POWEROFF - // The device's force feedback system is currently not // available. // This flag will not be set if the device cannot report // its power state. // DIGFFS_POWERON - // The device's force feedback system is currently // available. // This flag will not be set if the device cannot report // its power state. // DIGFFS_SAFETYSWITCHOFF - // The device's safety switch is currently in the off // position and the device cannot operate. // This flag will not be set if the device cannot report // the state of its safety switch. // DIGFFS_SAFETYSWITCHON - // The device's safety switch is currently on and the // device can operate. // This flag will not be set if the device cannot report // the state of its safety switch. // DIGFFS_STOPPED - // The device is not paused and no effects are playing. // DIGFFS_USERFFSWITCHOFF - // The device's user force feedback switch is currently // off and the device cannot operate. // This flag will not be set if the device cannot report // the state of its user force feedback switch. // DIGFFS_USERFFSWITCHON - // The device's user force feedback switch is currently on // and the device can operate. // This flag will not be set if the device cannot report // the state of its user force feedback switch. // -------------------------------------------------------------------------- HRESULT __fastcall TDx_InputDevice::GetForceFeedbackState( dword* pOut ) { // Original Function Definition // HRESULT GetForceFeedbackState( // LPDWORD pdwOut // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetForceFeedbackState()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->GetForceFeedbackState( (LPDWORD) pOut ); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetForceFeedbackState()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return fErrorValue; } // Success! return fErrorValue; } // -------------------------------------------------------------------------- // Method: GetObjectInfo() // Description: The GetObjectInfo() method will return device object // information for objects like buttons or axes. // // Error values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // DIERR_OBJECTNOTFOUND // Params: pDeviceObjectInstance - // The DeviceObjectInstance parameter references a // TDIDeviceObjectInstance component for holding information // about the object if the method returns successfully. // pObject - // The Object parameter identifies the target object of the // information retrieval. // // The How parameter determines how this parameter is to be // interpreted. // pFlags - // The Flags parameter defines flags indicating how the Object // parameter should be interpreted. // The described effect applies when the flag is set. // Flags: // DIPH_BYID - // The Obj parameter holds an object instance identifier // that identifies the object for which data is being // retrieved. // DIPH_BYOFFSET - // The Obj parameter holds an offset into the data format // of the object from which data is being retrieved. // DIPH_BYUSAGE - // The Obj parameter holds the HID usage page and usage // values of the object that have been combined using the // DIMAKEUSAGEDWORD macro. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::GetObjectInfo( TDIDeviceObjectInstance* pDeviceObjectInstance, dword pObject, dword pFlags ) { // Original Function Definition // HRESULT GetObjectInfo( // LPDIDEVICEOBJECTINSTANCE pdidoi, // DWORD dwObj, // DWORD dwHow // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetObjectInfo()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pDeviceObjectInstance==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetObjectInfo()", "TDX_BADPARAMS", "'pDeviceObjectInstance' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->GetObjectInfo( pDeviceObjectInstance->Internal_DIDEVICEOBJECTINSTANCE_Ptr, (DWORD) pObject, (DWORD) pFlags ); // Translate Data returned from Function pDeviceObjectInstance->Internal_DIDEVICEOBJECTINSTANCE_Update(); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetObjectInfo()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: GetProperty() // Description: The TDx_InputDevice::GetProperty() method will retrieve a // variety of property information from the input device. // // Error values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // DIERR_OBJECTNOTFOUND // DIERR_UNSUPPORTED // Params: pProp - // The Prop property identifies the property that is to be // retrieved. // // This is one of the predefined values below or a pointer a // GUID identifying the property. // // DIPROP_AUTOCENTER // Determine if the device is self centering. // The associated TDIPropDWORD::Data property will be set to // DIPROPAUTOCENTER_ON or DIPROPAUTOCENTER_OFF. // Not all devices support auto centering and sometimes the // autocentering mechanism can interfere with force feedback // effects. // // DIPROP_AXISMODE // Retrieve the axis mode. // The associated TDIPropDWORD::Data property will be set to // DIPROPAXISMODE_REL or DIPROPAXISMODE_ABS. // // DIPROP_BUFFERSIZE // Retrive the buffer size. // The associated TDIPropDWORD::Data property will be set to the // retrieved value. // This indicates the amount of data the device can buffer // between calls to TDx_InputDevice::GetDeviceData() without // data being lost. // // DIPROP_DEADZONE // Retrieve the deadzone value for a joystick. // The associated TDIPropDWORD::Data property will be set to the // retrieved value, which will be in the range 0 to 10000. // // DIPROP_FFGAIN // Retrieve the gain setting of the device. // The associated TDIPropDWORD::Data property will be set to the // retrieved value, which will be in the range 0 to 10000. // // DIPROP_FFLOAD // Retrieve the percentage of the device's memory is currently // in use. // The associated TDIPropDWORD::Data property will be set to the // retrieved value, which will be in the range 0 to 100. // // DIPROP_GRANULARITY // Retrieve the input granularity. // The associated TDIPropDWORD::Data property will be set to the // retrieved value, which represents the smallest amount of axis // movement a device can report. // // DIPROP_GUIDANDPATH // Retrieve the class identifier and device interface for the // device. // The associated TDIPropGuidAndPath::Class and // TDIPropGuidAndPath::Path properties will be set to the // retrieved values, which allow unsupported operations to be // performed on a HID. // // DIPROP_INSTANCENAME // Retrieve the friendly instance name of the device. // The associated TDIPropString::String property will be set to // the retrieved name, which will be something like 'joystick 2' // or 'mouse 1'. // // DIPROP_PRODUCTNAME // Retrieve the friendly product name of the device. // The associated TDIPropString::String property will be set to // the retrieved name, which will be something like // 'FlightMaster' or 'Super Trackball 3'. // // DIPROP_RANGE // Retrieve the range of values the device object can report. // The associated TDIPropRange::Min and TDIPropRange::Max // properties will be set to the retrieved ranges. // // DIPROP_SATURATION // Retrieve the current saturation zone value for a joystick. // The associated TDIPropDWORD::Data property will be set to the // retrieved value, which represents the point on an axis where // the device is considered to have reached its most extreeme // position. // pProperty - // The Property parameter references a single // TDIProperty-derived component: TDIPropRange, TDIPropDWORD, // TDIPropString or TDIPropGuidAndPath, depending on the kind of // property being set. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::GetProperty( REFGUID pProp, TDIProperty* pProperty ) { // Original Function Definition // HRESULT GetProperty( // REFGUID rguidProp, // LPDIPROPHEADER pdiph // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::GetProperty()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pProperty==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::GetProperty()", "TDX_BADPARAMS", "'pProperty' cannot be 'NULL'"); return false; } // Call Original Function // and Translate Data returned from Function AnsiString class_name = pProperty->ClassType()->ClassName(); if (class_name=="TDIPropDWORD") { TDIPropDWORD* component = (TDIPropDWORD*) pProperty; fErrorValue = fLPDIRECTINPUTDEVICE7->GetProperty( pProp, (DIPROPHEADER*) component->Internal_DIPROPDWORD_Ptr ); component->Internal_DIPROPDWORD_Update(); } else if (class_name=="TDIPropGuidAndPath") { TDIPropGuidAndPath* component = (TDIPropGuidAndPath*) pProperty; fErrorValue = fLPDIRECTINPUTDEVICE7->GetProperty( pProp, (DIPROPHEADER*) component->Internal_DIPROPGUIDANDPATH_Ptr ); component->Internal_DIPROPGUIDANDPATH_Update(); } else if (class_name=="TDIPropRange") { TDIPropRange* component = (TDIPropRange*) pProperty; fErrorValue = fLPDIRECTINPUTDEVICE7->GetProperty( pProp, (DIPROPHEADER*) component->Internal_DIPROPRANGE_Ptr ); component->Internal_DIPROPRANGE_Update(); } else if (class_name=="TDIPropString") { TDIPropString* component = (TDIPropString*) pProperty; fErrorValue = fLPDIRECTINPUTDEVICE7->GetProperty( pProp, (DIPROPHEADER*) component->Internal_DIPROPSTRING_Ptr ); component->Internal_DIPROPSTRING_Update(); } else { fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::GetProperty()", "TDX_ERROR", "You have passed a component* that is not one of the predefined TDIProperty derived types: TDIPropDWORD, TDIPropGuidAndPath, TDIPropRange, TDIPropString. Try passing in the appropriate component type" ); return false; } // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::GetProperty()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Internal_EnumCreatedEffectObjectsCallback() // Description: The Internal_EnumCreatedEffectObjectsCallback() method is // used internally by the TDx_Input_Library to redirect the // DirectX callback's triggered during the // EnumCreatedEffectObjects() method call to a // user-configurable OnEnumCreatedEffectObjects() event. // Params: pEffect - // The Effect parameter references the DirectX-supplied // DIRECTINPUTEFFECT structure that is currently being // enumerated. // pContext - // The Context parameter is a user defined value passed to the // calling function and sent to this method during each // enumeration. // -------------------------------------------------------------------------- BOOL __stdcall TDx_InputDevice::Internal_EnumCreatedEffectObjectsCallback( LPDIRECTINPUTEFFECT pEffect, LPVOID pContext ) { // Original Function Definition // BOOL CALLBACK DIEnumDevicesProc( // LPCDIDEVICEINSTANCE lpddi, // LPVOID pvRef // ); // Allocate temporary storage for converted data TDx_InputEffect* effect = new TDx_InputEffect(NULL); if (effect==NULL) { TDx_InputDevice_OnEnumCreatedEffectObjectsOwner->fErrorValue = DIERR_OUTOFMEMORY; if (TDx_InputDevice_OnEnumCreatedEffectObjectsOwner->FOnError) TDx_InputDevice_OnEnumCreatedEffectObjectsOwner->FOnError( TDx_InputDevice_OnEnumCreatedEffectObjectsOwner, TDx_InputDevice_OnEnumCreatedEffectObjectsOwner->Name+"::Internal_EnumCreatedEffectObjects()", TDx_Input_Library_ErrorString(TDx_InputDevice_OnEnumCreatedEffectObjectsOwner->fErrorValue), TDx_Input_Library_ErrorMessage(TDx_InputDevice_OnEnumCreatedEffectObjectsOwner->fErrorValue) ); } // Translate Parameters effect->Internal_LPDIRECTINPUTEFFECT = pEffect; // Call Event bool finished = false; if (TDx_InputDevice_OnEnumCreatedEffectObjectsOwner->OnEnumCreatedEffectObjects) TDx_InputDevice_OnEnumCreatedEffectObjectsOwner->OnEnumCreatedEffectObjects( TDx_InputDevice_OnEnumCreatedEffectObjectsOwner, effect, pContext, finished ); // cleanup delete effect; // Finished! if (finished) return DIENUM_STOP; return DIENUM_CONTINUE; } // -------------------------------------------------------------------------- // Method: Internal_EnumEffectsCallback() // Description: The Internal_EnumEffectsCallback() method is used internally // by the TDx_Input_Library to redirect the DirectX callback's // triggered during the EnumEffects() method call to a // user-configurable OnEnumEffects() event. // Params: pEffectInfo - // The EffectInfo parameter references the DirectX-supplied // DIEFFECTINFO structure that is currently being enumerated. // pContext - // The Context parameter is a user defined value passed to the // calling function and sent to this method during each // enumeration. // -------------------------------------------------------------------------- BOOL __stdcall TDx_InputDevice::Internal_EnumEffectsCallback( LPCDIEFFECTINFO pEffectInfo, LPVOID pContext ) { // Original Function Definition // BOOL CALLBACK DIEnumEffectsProc( // LPCDIEFFECTINFO pdei, // LPVOID pvRef // ); // Allocate temporary storage for converted data TDIEffectInfo* effect_info = new TDIEffectInfo(NULL); if (effect_info==NULL) { TDx_InputDevice_OnEnumEffectsOwner->fErrorValue = DIERR_OUTOFMEMORY; if (TDx_InputDevice_OnEnumEffectsOwner->FOnError) TDx_InputDevice_OnEnumEffectsOwner->FOnError( TDx_InputDevice_OnEnumEffectsOwner, TDx_InputDevice_OnEnumEffectsOwner->Name+"::Internal_EnumEffectsCallback()", TDx_Input_Library_ErrorString(TDx_InputDevice_OnEnumEffectsOwner->fErrorValue), TDx_Input_Library_ErrorMessage(TDx_InputDevice_OnEnumEffectsOwner->fErrorValue) ); } // Translate Parameters CopyMemory( effect_info->Internal_DIEFFECTINFO_Ptr, pEffectInfo, pEffectInfo->dwSize ); // Call Event bool finished = false; if (TDx_InputDevice_OnEnumEffectsOwner->OnEnumEffects) TDx_InputDevice_OnEnumEffectsOwner->OnEnumEffects( TDx_InputDevice_OnEnumEffectsOwner, effect_info, pContext, finished ); // cleanup delete effect_info; // Finished! if (finished) return DIENUM_STOP; return DIENUM_CONTINUE; } // -------------------------------------------------------------------------- // Method: Internal_EnumEffectsInFileCallback() // Description: The Internal_EnumEffectsInFileCallback() method is used // internally by the TDx_Input_Library to redirect the DirectX // callback's triggered during the EnumEffectsInFile() method // call to a user-configurable OnEnumEffectsInFile() event. // Params: pFileEffect - // The FileEffect parameter references the DirectX-supplied // DIFILEEFFECT structure that is currently being enumerated. // pContext - // The Context parameter is a user defined value passed to the // calling function and sent to this method during each // enumeration. // -------------------------------------------------------------------------- BOOL __stdcall TDx_InputDevice::Internal_EnumEffectsInFileCallback( LPCDIFILEEFFECT pFileEffect, LPVOID pContext ) { // Original Function Definition // BOOL CALLBACK DIEnumEffectsInFileCallback( // LPCDIFILEEFFECT lpDiFileEf, // LPVOID pvRef // ); // Allocate temporary storage for converted data TDIFileEffect* file_effect = new TDIFileEffect(NULL); if (file_effect==NULL) { TDx_InputDevice_OnEnumEffectsInFileOwner->fErrorValue = DIERR_OUTOFMEMORY; if (TDx_InputDevice_OnEnumEffectsInFileOwner->FOnError) TDx_InputDevice_OnEnumEffectsInFileOwner->FOnError( TDx_InputDevice_OnEnumEffectsInFileOwner, TDx_InputDevice_OnEnumEffectsInFileOwner->Name+"::Internal_EnumEffectsCallback()", TDx_Input_Library_ErrorString(TDx_InputDevice_OnEnumEffectsInFileOwner->fErrorValue), TDx_Input_Library_ErrorMessage(TDx_InputDevice_OnEnumEffectsInFileOwner->fErrorValue) ); } // Translate Parameters CopyMemory( file_effect->Internal_DIFILEEFFECT_Ptr, pFileEffect, pFileEffect->dwSize ); // Call Event bool finished = false; if (TDx_InputDevice_OnEnumEffectsInFileOwner->OnEnumEffectsInFile) TDx_InputDevice_OnEnumEffectsInFileOwner->OnEnumEffectsInFile( TDx_InputDevice_OnEnumEffectsInFileOwner, file_effect, pContext, finished ); // cleanup delete file_effect; // Finished! if (finished) return DIENUM_STOP; return DIENUM_CONTINUE; } // -------------------------------------------------------------------------- // Method: Internal_EnumObjectsCallback() // Description: The Internal_EnumObjectsCallback() method is used internally // by the TDx_Input_Library to redirect the DirectX callback's // triggered during the EnumObjects() method call to a // user-configurable OnEnumObjects() event. // Params: pDeviceObjectInstance - // The DeviceObjectInstance parameter references the // DirectX-supplied DIDEVICEOBJECTINSTANCE structure that is // currently being enumerated. // pContext - // The Context parameter is a user defined value passed to the // calling function and sent to this method during each // enumeration. // -------------------------------------------------------------------------- BOOL __stdcall TDx_InputDevice::Internal_EnumObjectsCallback( LPCDIDEVICEOBJECTINSTANCE pDeviceObjectInstance, LPVOID pContext ) { // Original Function Definition // BOOL CALLBACK DIEnumDeviceObjectsProc( // LPCDIDEVICEOBJECTINSTANCE lpddoi, // LPVOID pvRef // ); // Allocate temporary storage for converted data TDIDeviceObjectInstance* device_object_instance = new TDIDeviceObjectInstance(NULL); if (device_object_instance==NULL) { TDx_InputDevice_OnEnumObjectsOwner->fErrorValue = DIERR_OUTOFMEMORY; if (TDx_InputDevice_OnEnumObjectsOwner->FOnError) TDx_InputDevice_OnEnumObjectsOwner->FOnError( TDx_InputDevice_OnEnumObjectsOwner, TDx_InputDevice_OnEnumObjectsOwner->Name+"::Internal_EnumObjects()", TDx_Input_Library_ErrorString(TDx_InputDevice_OnEnumObjectsOwner->fErrorValue), TDx_Input_Library_ErrorMessage(TDx_InputDevice_OnEnumObjectsOwner->fErrorValue) ); } // Translate Parameters CopyMemory(device_object_instance->Internal_DIDEVICEOBJECTINSTANCE_Ptr, pDeviceObjectInstance, pDeviceObjectInstance->dwSize ); // Call Event bool finished = false; if (TDx_InputDevice_OnEnumObjectsOwner->OnEnumObjects) TDx_InputDevice_OnEnumObjectsOwner->OnEnumObjects( TDx_InputDevice_OnEnumObjectsOwner, device_object_instance, pContext, finished ); // cleanup delete device_object_instance; // Finished! if (finished) return DIENUM_STOP; return DIENUM_CONTINUE; } // -------------------------------------------------------------------------- // Method: Poll() // Description: The Poll() method will retrieve data, update the state and // generate input and set notification events for a polled // object of an input device. // // If a device requires polling, no new data will be recieved // from the device until this method is called. // For devices that do not require polling, this method will // have no effect. // // The data format must be set using // TDx_InputDevice::SetDataFormat() and the device acquired with // TDx_InputDevice::Acquire() before the object can be polled. // // Error Values that can be generated are: // // DIERR_INPUTLOST // DIERR_NOTACQUIRED // DIERR_NOTINITIALIZED // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::Poll() { // Original Function Definition // HRESULT Poll(); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Poll()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->Poll( ); // Handle any Known Results if ((fErrorValue!=DI_OK) && (fErrorValue!=DI_NOEFFECT)) { // Failure. if (FOnError) FOnError( this, Name+"::Poll()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: RunControlPanel() // Description: The RunControlPanel() method will run the control panel // associated with the device. // // The default device control panel will be launched if no // association has been made. // // Error Values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pOwner - // The Owner parameter defines the handle of the parent window // of the control panel user interface. // // Setting this parameter to NULL results in no parent window // being used. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::RunControlPanel( HWND pOwner ) { // Original Function Definition // HRESULT RunControlPanel( // HWND hwndOwner, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::RunControlPanel()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->RunControlPanel( pOwner, 0 ); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::RunControlPanel()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SendDeviceData() // Description: The SendDeviceData() method will send data to an acquired // device capable of accepting output. // // The order in which individual elements are sent is unknown. // Sending multiple pieces of data to one object with one call // will result in only one (unspecified) piece of data being // sent. // // For specific results, the data should be sent in successive // calls, one data element per call. // The DISDD_CONTINUE flag can be used to overlay data from // successive method calls. // // Error Values that can be generated are: // // DIERR_INPUTLOST // DIERR_NOTACQUIRED // DIERR_REPORTFULL // DIERR_UNPLUGGED // Params: pObjectData - // The ObjectData parameter defines the size, in bytes, of one // of the TDIDeviceObjectData elements in the DeviceObjectData // array. // pDeviceObjectData - // The DeviceObjectData parameter references an array of // TDIDeviceObjectData components holding the data being sent to // the device. // pInOut - // The InOut parameter initially holds the number of elements in // the DeviceObjectData array and holds the actual number of // elements sent to the device on returning. // pFlags - // The Flags parameter define a flag indicating how data should // be sent to the device. // The described effect applies when the flag is set. // Flags: // DISDD_CONTINUE - // Device data will overlay any previously sent data. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::SendDeviceData( dword pObjectData, TDIDeviceObjectData* pDeviceObjectData, dword* pInOut, dword pFlags ) { // Original Function Definition // HRESULT SendDeviceData( // DWORD cbObjectData, // LPCDIDEVICEOBJECTDATA rgdod, // LPDWORD pdwInOut, // DWORD fl // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SendDeviceData()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pDeviceObjectData==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::SendDeviceData()", "TDX_BADPARAMS", "'pDeviceObjectData' cannot be 'NULL'"); return false; } if (pInOut==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::SendDeviceData()", "TDX_BADPARAMS", "'pInOut' cannot be 'NULL'"); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->SendDeviceData( (DWORD) pObjectData, pDeviceObjectData->Internal_DIDEVICEOBJECTDATA_Ptr, (LPDWORD) pInOut, (DWORD) pFlags ); // Translate Data returned from Function pDeviceObjectData->Internal_DIDEVICEOBJECTDATA_Update(); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SendDeviceData()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SendForceFeedbackCommand() // Description: The SendForceFeedbackCommand() method will send the device // force feedback system a command. // // This method requires exclusive mode access to an acquired // device. // // Error Values that can be generated are: // // DIERR_INPUTLOST // DIERR_INVALIDPARAM // DIERR_NOTEXCLUSIVEACQUIRED // DIERR_NOTINITIALIZED // DIERR_UNSUPPORTED // Params: pFlags - // The Flags parameter defines flags identifying the command to // be sent to the force feedback system of the device. // The described effect applies when the flag is set. // Flags: // DISFFC_CONTINUE - // Continue playback of any active effects that are // currently paused. // // This command will generate an error when applied to a // device that is not paused. // DISFFC_PAUSE - // Pause playback of any active effects the device is // currently playing. // // An effect will continue to play to its full duration // when a DISFFC_CONTINUE command is sent. // Modifying or starting effects while the device is // paused may cause undefined behaviour. // DISFCC_RESET or DISFCC_STOPALL will abandon the pause // and stop all effects. // DISFFC_RESET - // Reset the force feedback system to its startup state // for this device. // // This disables the device's actuators and wipes all // effects are from the device. // Effects must be recreated if further use is desired. // DISFFC_SETACTUATORSOFF - // Disable the force feedback actuators for this device. // Effects will continue to be played, but are ignored by // the device. // DISFFC_SETACTUATORSON - // Enable the force feedback actuators for this device. // DISFFC_STOPALL - // Halt and reset any active effects currently playing on // the device. // // This command is equivilent to calling // TDx_InputDevice::Stop for each effect and will also // unpause the device. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::SendForceFeedbackCommand( dword pFlags ) { // Original Function Definition // HRESULT SendForceFeedbackCommand( // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SendForceFeedbackCommand()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->SendForceFeedbackCommand( (DWORD) pFlags ); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SendForceFeedbackCommand()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetCooperativeLevel() // Description: The SetCooperativeLevel() method will establish this device // instance's cooperative level. // // Acquiring the system mouse in exclusive mode will cause the // mouse pointer to disappear until the device is unaquired. // // You will need to call this method before calling // TDx_InputDevice::Acquire(). // // Error Values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pHWnd - // The HWnd parameter defines the window handle being associated // with the device. // // This is a valid top level window handle belonging to this // process. // The associated window must not be destroyed while the device // is still active. // pFlags - // The Flags parameter defines flags indicating the cooperative // level being set for the device. // The described effect applies when the flag is set. // Flags: // DISCL_BACKGROUND - // Background access is required. // // The device may be acquired anytime, even when its // associated window is not active. // This flag or DISCL_FOREGROUND must be set, but not // both. // DISCL_EXCLUSIVE - // Exclusive access is required. // No other device instance can gain exclusive access // while the device is acquired. // This flag or DISCL_NONEXCLUSIVE must be set, but not // both. // DISCL_FOREGROUND - // Foreground access is required. // The device will be automatically unacquired whenever // its associated window moves to the background. // This flag or DISCL_BACKGROUND must be set, but not // both. // DISCL_NONEXCLUSIVE - // Non exclusive access is required. // Multiple applications can access the device without // interference. // This flag or DISCL_EXCLUSIVE must be set, but not both. // DISCL_NOWINKEY - // The Windows key is to be disabled. // // This is useful for preventing accidental exits from the // applicaiton. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::SetCooperativeLevel( HWND pHWnd, dword pFlags ) { // Original Function Definition // HRESULT SetCooperativeLevel( // HWND hwnd, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetCooperativeLevel()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->SetCooperativeLevel( pHWnd, (DWORD) pFlags ); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetCooperativeLevel()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetDataFormat() // Description: The SetDataFormat() method will set the device's data format. // // Note: This method is different in use to it's sdk equivalent, // in that you pass in a TDIData* instead of a global // structure, which means you can supply any component derived // from TDIData, the pre-defined TDIKeyboardState, // TDIMouseState, TDIMouseState2, TDIJoyState, TDIJoyState2 // components and the TDIDataFormat component for custom // configurations. // // After this method is called with any of the predefined // components, call the TDx_InputDevice::GetDeviceState() method // and pass in the same component, otherwise an error may occur. // // You should only need to set a device's data format once, and // note that the data format cannot be changed while the device // is acquired. // // Error Values that can be generated are: // DIERR_ACQUIRED // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pDataFormat - // The DataFormat parameter references the data format to be set // for the device. The data format may be an application defined // TDIDataFormat component or one of the predefined components // below. // // TDIKeyboardState - basic system keyboard // TDIMouseState - standard mouse // TDIMouseState2 - advanced mouse // TDIJoyState - standard joystick // TDIJoyState2 - advanced joystick // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::SetDataFormat( TDIData* pDataFormat ) { // Original Function Definition // HRESULT SetDataFormat( // LPCDIDATAFORMAT lpdf // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetDataFormat()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pDataFormat==NULL) { fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::SetDataFormat()", "TDX_BADPARAMS", "'pDataFormat' cannot be 'NULL'"); return false; } // Call Original Function AnsiString class_name = pDataFormat->ClassType()->ClassName(); if (class_name=="TDIMouseState") fErrorValue = fLPDIRECTINPUTDEVICE7->SetDataFormat(&c_dfDIMouse); else if (class_name=="TDIMouseState2") fErrorValue = fLPDIRECTINPUTDEVICE7->SetDataFormat(&c_dfDIMouse2); else if (class_name=="TDIJoyState") fErrorValue = fLPDIRECTINPUTDEVICE7->SetDataFormat(&c_dfDIJoystick); else if (class_name=="TDIJoyState2") fErrorValue = fLPDIRECTINPUTDEVICE7->SetDataFormat(&c_dfDIJoystick2); else if (class_name=="TDIKeyboardState") fErrorValue = fLPDIRECTINPUTDEVICE7->SetDataFormat(&c_dfDIKeyboard); else if (class_name=="TDIDataFormat") { TDIDataFormat* component = (TDIDataFormat*) pDataFormat; fErrorValue = fLPDIRECTINPUTDEVICE7->SetDataFormat( component->Internal_DIDATAFORMAT_Ptr ); } // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::SetDataFormat()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Save the component last used fLastDataFormat = pDataFormat; // Finished! return true; } // -------------------------------------------------------------------------- // Method: SetEventNotification() // Description: The SetEventNotification() method will specify the device's // notification event status and will set the notification event // triggered the device state changes. // // Device state changes include axis position change, button // state change, POV control direction change or loss of // acquisition. // // Note: this method has been slightly altered from the directx // equivalent. You no longer need to create an event, enable // notifications, disable notifications. Instead, you can simply // toggle between the TDx_InputDevice::OnDeviceStateChange() // events and polled mode. // // Error Values that can be generated are: // // DIERR_ACQUIRED // DIERR_HANDLEEXISTS // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // Params: pEventNotification - // The EventNotification parameter should be set to true for the // TDx_InputDevice::OnDeviceStateChange() Event to be triggered // by changes in the device state. // Setting it to false will disable this facility, allowing // polled access to the device only. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::SetEventNotification( bool pEventNotification ) { // Original Function Definition // HRESULT SetEventNotification( // HANDLE hEvent // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetEventNotification()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // pause the thread if (TDx_InputDevice_Thread) TDx_InputDevice_Thread->Pause(); // if notifications are being Disabled if (!pEventNotification) { // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->SetEventNotification( NULL ); // delete the event handle if (fEventHandle!=NULL) { CloseHandle(fEventHandle); fEventHandle = NULL; } // remove from list if (TDx_InputDevice_ComponentList) if (TDx_InputDevice_ComponentList->IndexOf(this)!=-1) TDx_InputDevice_ComponentList->Delete(TDx_InputDevice_ComponentList->IndexOf(this)); // restart the thread if (TDx_InputDevice_Thread) { TDx_InputDevice_Thread->HandlesModified = true; TDx_InputDevice_Thread->Restart(); } return true; } // notifications are being Enabled if (fEventHandle==NULL) { fEventHandle = CreateEvent( NULL, FALSE, FALSE, NULL ); if (fEventHandle == NULL) { fErrorValue = DIERR_OUTOFMEMORY; if (FOnError) FOnError( this, Name+"::Create()", "DIERR_OUTOFMEMORY", "The "+Name+" thread handle could not be created successfully." ); if (TDx_InputDevice_Thread) TDx_InputDevice_Thread->Restart(); return false; } } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->SetEventNotification( fEventHandle ); // Handle any Known Results if (fErrorValue!=DI_OK) { if (FOnError) FOnError( this, Name+"::SetEventNotification()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); if (TDx_InputDevice_Thread) { TDx_InputDevice_Thread->HandlesModified = true; TDx_InputDevice_Thread->Restart(); } return false; } // everything worked ok, add to list if (TDx_InputDevice_ComponentList) if (TDx_InputDevice_ComponentList->IndexOf(this)==-1) TDx_InputDevice_ComponentList->Add(this); // restart the thread if (TDx_InputDevice_Thread) { TDx_InputDevice_Thread->HandlesModified = true; TDx_InputDevice_Thread->Restart(); } // Success! return true; } // -------------------------------------------------------------------------- // Method: SetProperty() // Description: The SetProperty() method will define various device behaviour // properties such as input buffer sizes and axis modes. // // Error Values that can be generated are: // // DIERR_INVALIDPARAM // DIERR_NOTINITIALIZED // DIERR_OBJECTNOTFOUND // DIERR_UNSUPPORTED // Params: pProp - // The Prop property identifies the property that is to be // retrieved. // // This is one of the predefined values below or a pointer a // GUID identifying the property. // // DIPROP_AUTOCENTER // Set the device's auto centering function. // The associated TDIPropDWORD::Data property should be set to // DIPROPAUTOCENTER_ON or DIPROPAUTOCENTER_OFF. // Not all devices support auto centering and sometimes the // autocentering mechanism can interfere with force feedback // effects. // // DIPROP_AXISMODE // Set the axis mode. // The associated TDIPropDWORD::Data property should be set to // DIPROPAXISMODE_REL or DIPROPAXISMODE_ABS. // // DIPROP_BUFFERSIZE // Set the buffer size. // The associated TDIPropDWORD::Data property should be set to // the desired value, which will be adjusted if it is larger // than the device can support. // This indicates the amount of data the device can buffer // between calls to TDx_InputDevice::GetDeviceData() without // data being lost. // // DIPROP_CALIBRATIONMODE // Set the calibration mode for an axis or device. // The associated TDIPropDWORD::Data property should be set to // DIPROPCALIBRATIONMODE_RAW or DIPROPCALIBRATIONMODE_COOKED // (the default). // The RAW setting causes raw, uncalibrated data to be returned // and the deadzone, saturation and range settings to be // ignored. // // DIPROP_DEADZONE // Set the deadzone value for a joystick. // The associated TDIPropDWORD::Data property should be set to // the desired value, in the range of 0 to 10000. // // DIPROP_FFGAIN // Set the gain value for the device. // The associated TDIPropDWORD::Data property should be set to // the desired value, in the range of 0 to 10000. // // DIPROP_INSTANCENAME // Set the friendly instance name of the device. // The associated TDIPropString::String property should be set // to the desired name, something like 'joystick 2' or 'mouse // 1'. // It generally shouldn't be neccessary to modify a device's // instance name. // // DIPROP_PRODUCTNAME // Set the friendly product name of the device. // The associated TDIPropString::String property should be set // to the desired name, which will be something like // 'FlightMaster' or 'Super Trackball 3'. // It generally shouldn't be neccessary to modify a device's // product name. // // DIPROP_RANGE // Set the range of values the device object can report. // The associated TDIPropRange::Min must be set to a smaller // value than TDIPropRange::Max. // For some devices this is a read only property and this // command will fail. // // DIPROP_SATURATION // Set the saturation zone value for a joystick. // The associated TDIPropDWORD::Data property should be set to // the desired value, which represents the point on an axis // where the device is considered to have reached its most // extreme position. // pProperty - // The Property parameter references a single // TDIProperty-derived component: TDIPropRange, TDIPropDWORD, // TDIPropString or TDIPropGuidAndPath, depending on the kind of // property being set. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::SetProperty( REFGUID pProp, TDIProperty* pProperty ) { // Original Function Definition // HRESULT SetProperty( // REFGUID rguidProp, // LPCDIPROPHEADER pdiph // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::SetProperty()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Check Parameters for Accuracy if (pProperty==NULL) { fErrorValue = TDX_BADPARAMS; if (FOnError) FOnError( this, Name+"::SetProperty()", "TDX_BADPARAMS", "'pProperty' cannot be 'NULL'"); return false; } // Call Original Function // and Translate Data returned from Function AnsiString class_name = pProperty->ClassType()->ClassName(); if (class_name=="TDIPropDWORD") { TDIPropDWORD* component = (TDIPropDWORD*) pProperty; fErrorValue = fLPDIRECTINPUTDEVICE7->SetProperty( pProp, (DIPROPHEADER*) component->Internal_DIPROPDWORD_Ptr ); component->Internal_DIPROPDWORD_Update(); } else if (class_name=="TDIPropGuidAndPath") { TDIPropGuidAndPath* component = (TDIPropGuidAndPath*) pProperty; fErrorValue = fLPDIRECTINPUTDEVICE7->SetProperty( pProp, (DIPROPHEADER*) component->Internal_DIPROPGUIDANDPATH_Ptr ); component->Internal_DIPROPGUIDANDPATH_Update(); } else if (class_name=="TDIPropRange") { TDIPropRange* component = (TDIPropRange*) pProperty; fErrorValue = fLPDIRECTINPUTDEVICE7->SetProperty( pProp, (DIPROPHEADER*) component->Internal_DIPROPRANGE_Ptr ); component->Internal_DIPROPRANGE_Update(); } else if (class_name=="TDIPropString") { TDIPropString* component = (TDIPropString*) pProperty; fErrorValue = fLPDIRECTINPUTDEVICE7->SetProperty( pProp, (DIPROPHEADER*) component->Internal_DIPROPSTRING_Ptr ); component->Internal_DIPROPSTRING_Update(); } else { fErrorValue = TDX_ERROR; if (FOnError) FOnError( this, Name+"::SetProperty()", "TDX_ERROR", "You have passed a component* that is not one of the predefined TDIProperty derived types: TDIPropDWORD, TDIPropGuidAndPath, TDIPropRange, TDIPropString. Try passing in the appropriate component type" ); return false; } // Handle any Known Results if ((fErrorValue!=DI_OK) && (fErrorValue!=DI_PROPNOEFFECT)) { // Failure. if (FOnError) FOnError( this, Name+"::SetProperty()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: Unacquire() // Description: The Unacquire() method will release access to a previously // acquired device. // // Unaquiring an unaquired device will cause an error. // // Error Values that can be generated are: // // DI_NOEFFECT // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::Unacquire() { // Original Function Definition // HRESULT Unacquire(); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::Unacquire()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->Unacquire( ); // Handle any Known Results if ((fErrorValue!=DI_OK) && (fErrorValue!=DI_NOEFFECT)) { // Failure. if (FOnError) FOnError( this, Name+"::Unacquire()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Method: WriteEffectToFile() // Description: The WriteEffectToFile() method will save one or more force // feedback effects to a file. // // Once written, the effects can be retrieved by using the // TDx_InputDevice::EnumEffectsInFile() method. // // Error Values that can be generated are: // // DIERR_INVALIDPARAM // Params: pFileName - // The FileName parameter defines the name of the RIFF file // being written. // pEntries - // The Entries parameter defines the number of elements in the // FileEffect array. // pFileEffect - // The FileEffect parameter references an array of TDIFileEffect // components holding the effect information to be saved to // file. // pFlags - // The Flags parameter defines flags indicating how the effect // should be written. // The described effect applies when the flag is set. // Flags: // DIFEF_DEFAULT - // Setting this flag is equivilent to setting the // parameter to 0. // DIFEF_INCLUDENONSTANDARD - // Effects undefined by DirectInput should also be written // to the file. // // When this flag is not set, only defined effects such as // GUID_Condition will be written. // -------------------------------------------------------------------------- bool __fastcall TDx_InputDevice::WriteEffectToFile( AnsiString pFileName, dword pEntries, TDIFileEffect* pFileEffect, dword pFlags ) { // Original Function Definition // HRESULT WriteEffectToFile( // LPCSTR lpszFileName, // DWORD dwEntries, // LPCDIFILEEFFECT rgDiFileEft, // DWORD dwFlags // ); // if the component internals are not already created, exit if (!fCreated) { fErrorValue = TDX_NOTCREATED; if (FOnError) FOnError( this, Name+"::WriteEffectToFile()", "TDX_NOTCREATED", "The "+Name+" component has not been created successfully." ); return false; } // Translate Parameters before calling Original Function AnsiString TempFileName = pFileName; // Call Original Function fErrorValue = fLPDIRECTINPUTDEVICE7->WriteEffectToFile( (LPCSTR) TempFileName.c_str(), (DWORD) pEntries, (pFileEffect==NULL) ? NULL : pFileEffect->Internal_DIFILEEFFECT_Ptr, (DWORD) pFlags ); // Translate Data returned from Function if (pFileEffect!=NULL) pFileEffect->Internal_DIFILEEFFECT_Update(); // Handle any Known Results if (fErrorValue!=DI_OK) { // Failure. if (FOnError) FOnError( this, Name+"::WriteEffectToFile()", TDx_Input_Library_ErrorString(fErrorValue), TDx_Input_Library_ErrorMessage(fErrorValue) ); return false; } // Success! return true; } // -------------------------------------------------------------------------- // Internal Interface Access // -------------------------------------------------------------------------- LPDIRECTINPUTDEVICE7 __fastcall TDx_InputDevice::FGetInternal_LPDIRECTINPUTDEVICE7() { return fLPDIRECTINPUTDEVICE7; } // -------------------------------------------------------------------------- LPDIRECTINPUTDEVICE7* __fastcall TDx_InputDevice::FGetInternal_LPDIRECTINPUTDEVICE7_Ptr() { return &fLPDIRECTINPUTDEVICE7; } // -------------------------------------------------------------------------- void __fastcall TDx_InputDevice::FSetInternal_LPDIRECTINPUTDEVICE7( LPDIRECTINPUTDEVICE7 pLPDIRECTINPUTDEVICE7 ) { if (!fCreated) { fLPDIRECTINPUTDEVICE7 = pLPDIRECTINPUTDEVICE7; fCreated = (fLPDIRECTINPUTDEVICE7!=NULL); } } // -------------------------------------------------------------------------- void __fastcall TDx_InputDevice::Internal_LPDIRECTINPUTDEVICE7_Update() { fCreated = (fLPDIRECTINPUTDEVICE7!=NULL); } // -------------------------------------------------------------------------- LPDIRECTINPUTDEVICE __fastcall TDx_InputDevice::FGetInternal_LPDIRECTINPUTDEVICE() { return fLPDIRECTINPUTDEVICE; } // -------------------------------------------------------------------------- LPDIRECTINPUTDEVICE* __fastcall TDx_InputDevice::FGetInternal_LPDIRECTINPUTDEVICE_Ptr() { return &fLPDIRECTINPUTDEVICE; } // -------------------------------------------------------------------------- void __fastcall TDx_InputDevice::FSetInternal_LPDIRECTINPUTDEVICE( LPDIRECTINPUTDEVICE pLPDIRECTINPUTDEVICE ) { if (!fCreated) { fLPDIRECTINPUTDEVICE = pLPDIRECTINPUTDEVICE; fCreated = (fLPDIRECTINPUTDEVICE!=NULL); } } // -------------------------------------------------------------------------- void __fastcall TDx_InputDevice::Internal_LPDIRECTINPUTDEVICE_Update() { fCreated = (fLPDIRECTINPUTDEVICE7!=NULL); } // --------------------------------------------------------------------------