no ATL headers
Moderator: Moderators
no ATL headers
Hi,
I wonder if there is a way to use the latest SDK without including all of these ATL headers ?
Should I go back to the old SDK or is there any other solution to have the SpaceNavigator support in our engine without those headers ?
Cheers,
Gregory Jaegy
I wonder if there is a way to use the latest SDK without including all of these ATL headers ?
Should I go back to the old SDK or is there any other solution to have the SpaceNavigator support in our engine without those headers ?
Cheers,
Gregory Jaegy
Hi,
thanks for your answer. actually I am building a plain Win32 app (no MFC).
in order to use COM, one has to use CComPtr objects (CComPtr<ISensor> and CComPtr<IKeyboard>); this CComPtr objects are only defined in <atlbase>, so I have to include at least this header.
Does someone have an example of using the new COM API without any ATL include ?
thanks,
Gregory Jaegy
PS: currently my code looks like this. It works very well, but I still wonder if the same would be possible without this ATL header
thanks for your answer. actually I am building a plain Win32 app (no MFC).
in order to use COM, one has to use CComPtr objects (CComPtr<ISensor> and CComPtr<IKeyboard>); this CComPtr objects are only defined in <atlbase>, so I have to include at least this header.
Does someone have an example of using the new COM API without any ATL include ?
thanks,
Gregory Jaegy
PS: currently my code looks like this. It works very well, but I still wonder if the same would be possible without this ATL header
Code: Select all
#define _WIN32_DCOM
#include <atlbase>
using namespace ATL;
#import "progid:TDxInput.Device.1" no_namespace
#include "gjdisplay.h"
class gjSpaceNavigatorWrapper : public gjISpaceNavigatorWrapper
{
/****************************************************************************/
// PROTECTED MEMBERS
/****************************************************************************/
protected:
gjDouble m_dSensitivity;
CComPtr<ISensor> m_p3DSensor;
CComPtr<IKeyboard> m_p3DKeyboard;
gjInt64 m_iKeyStates;
gjSVector3Dd m_vTranslation;
gjSVector3Dd m_vAxis;
gjDouble m_dAngle;
/****************************************************************************/
// CONSTRUCTION
/****************************************************************************/
public:
/**
* Enter brief here...
*/
gjSpaceNavigatorWrapper() : gjISpaceNavigatorWrapper()
{
m_dSensitivity = 1.0;
m_iKeyStates = 0;
m_vTranslation.Set(0.0, 0.0, 0.0);
m_vAxis.Set(0.0, 1.0, 0.0);
m_dAngle = 0.0;
Initialize();
}
/****************************************************************************/
// DESTRUCTION
/****************************************************************************/
public:
/**
* Enter brief here...
*/
virtual ~gjSpaceNavigatorWrapper()
{
CleanUp();
}
/****************************************************************************/
// PUBLIC METHODES
/****************************************************************************/
public:
void CleanUp()
{
// destroy
CComPtr<ISimpleDevice> _3DxDevice;
// Release the sensor and keyboard interfaces
if (m_p3DSensor)
{
m_p3DSensor->get_Device((IDispatch**)&_3DxDevice);
m_p3DSensor.Release();
}
if (m_p3DKeyboard)
m_p3DKeyboard.Release();
if (_3DxDevice)
{
// Disconnect it from the driver
_3DxDevice->Disconnect();
_3DxDevice.Release();
}
}
void Initialize()
{
HRESULT hr=::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED );
if (!SUCCEEDED(hr))
{
gjStringBase strError;
strError.Format(gjT("CoInitializeEx failed / Error 0x%x"), hr);
gjDisplayApp::s_pTheApp->LogDisplay(strError);
return;
}
// create device
CComPtr<IUnknown> _3DxDevice;
// Create the device object
gjBool bDeviceFound = gjFALSE;
hr = _3DxDevice.CoCreateInstance(__uuidof(Device));
if (SUCCEEDED(hr))
{
CComPtr<ISimpleDevice> _3DxSimpleDevice;
hr = _3DxDevice.QueryInterface(&_3DxSimpleDevice);
if (SUCCEEDED(hr))
{
// Get the interfaces to the sensor and the keyboard;
m_p3DSensor = _3DxSimpleDevice->Sensor;
m_p3DKeyboard = _3DxSimpleDevice->Keyboard;
// Connect to the driver
_3DxSimpleDevice->Connect();
bDeviceFound = gjTRUE;
}
}
// log
gjStringBase sMessage;
if (bDeviceFound)
sMessage = gjT("SpaceNavigator device found");
else
sMessage = gjT("SpaceNavigator device not found");
gjDisplayApp::s_pTheApp->LogDisplay(sMessage);
}
virtual void Update()
{
m_vTranslation.Set(0.0f, 0.0f, 0.0f);
m_dAngle = 0.0;
m_vAxis.Set(0.0, 1.0, 0.0);
if (m_p3DKeyboard)
{
try
{ // Check if any change to the keyboard state
gjU32 nKeys;
nKeys = m_p3DKeyboard->Keys;
for (gjU32 i = 1; i <= nKeys; i++)
{
gjInt64 mask = (gjInt64)1<<i>IsKeyDown(i);
if (isPressed == VARIANT_TRUE)
{
if (!(m_iKeyStates & mask))
{
m_iKeyStates |= mask;
ExecuteKeyFunction(i);
}
}
else
{
m_iKeyStates &= ~mask;
}
}
// Test the special keys
for (gjU32 i = 30; i <= 31; i++)
{
gjInt64 mask = (gjInt64)1<<i>IsKeyDown(i);
if (isPressed == VARIANT_TRUE)
{
if (!(m_iKeyStates & mask))
{
m_iKeyStates |= mask;
ExecuteKeyFunction(i);
}
}
else
{
m_iKeyStates &= ~mask;
}
}
}
catch (_com_error &e)
{
// Some sort of exception handling
}
}
if (m_p3DSensor)
{
try
{
CComPtr<IAngleAxis> pRotation = m_p3DSensor->Rotation;
CComPtr<IVector3D> pTranslation = m_p3DSensor->Translation;
// Check if the cap is still displaced
if (pRotation->Angle > 0. || pTranslation->Length > 0.)
{
m_vTranslation.Set(pTranslation->X, pTranslation->Y, pTranslation->Z);
m_vAxis.Set(pRotation->X, pRotation->Y, pRotation->Z);
m_dAngle = pRotation->Angle;
}
pRotation.Release();
pTranslation.Release();
}
catch (_com_error &e)
{
// Some sort of exception handling
OutputDebugString(e.Description());
OutputDebugString(gjT("\n"));
if (e.Error() == 0x800401f0)
{
//CleanUp();
Initialize();
}
}
}
}
virtual gjSVector3Dd& GetTranslation() { return m_vTranslation; }
virtual void GetRotation(gjDouble& _dAngle, gjSVector3Dd& _vAxis) { _dAngle = m_dAngle; _vAxis.Set(m_vAxis.x, m_vAxis.y, m_vAxis.z); }
protected:
void ExecuteKeyFunction(gjInt _iKey)
{
gjStringBase sMessage;
sMessage.Format(gjT("SpaceNavigator button %i\n"), _iKey);
gjDisplayApp::s_pTheApp->LogDisplay(sMessage);
}
};
Hi gjaegy,
You have a couple of alternatives:
You do not have to use the CComPtr ATL class. This is an helper calls that wraps a pointer to an interface, a "smart pointer".in order to use COM, one has to use CComPtr objects (CComPtr<ISensor> and CComPtr<IKeyboard>)
You have a couple of alternatives:
- You can use the smart pointer as defined in the .tlh file (generated from the #import directive). For example, the code
would be replaced by
Code: Select all
CComPtr<ISimpleDevice> _3DxDevice;
.Code: Select all
SimpleDevicePtr _3DxDevice;
See the MSDN doc for more information on the "#import" directive. - Use regular C++ pointers. For example, the line
would be replaced by
Code: Select all
CComPtr<ISimpleDevice> _3DxDevice;
.Code: Select all
ISimpleDevice* _3DxDevice;
Note that you need carefully manage the "Release()" of such pointers.
Hi, thanks a lot for the information, to be honnest I don't have any experience with COM.
Using plain pointers (or _Ptr suffix), how should I handle the instanciation of the objects ? I guess I would have to call CoCreateInstance(), but I have no idea what the parameters should be. The first one should be __uuidof(Device) I think, but what about the other?
Thanks for the help, I really appreciate!
Using plain pointers (or _Ptr suffix), how should I handle the instanciation of the objects ? I guess I would have to call CoCreateInstance(), but I have no idea what the parameters should be. The first one should be __uuidof(Device) I think, but what about the other?
Thanks for the help, I really appreciate!
There are several options. Looking at the source for CComPtr<IUnknown>::CoCreateInstance (defined in atlcomcli.h), you could write something like:
Using smart pointers as automatically generated by the #import directive should be even simpler:
It is possible to write the above code in less lines of code but I think this is more clear.
Note: I wrote the above without actually trying to compile it. There may a few "spelling" mistakes.
Code: Select all
IUnknown* pUnknown = NULL;
HRESULT hr = ::CoCreateInstance(__uuidof(Device), NULL, CLSCTX_ALL, uuidof(IUnknown), &pUnknown);
if (SUCCEEDED(hr))
{
ISimpleDevice* pSimpleDevice = NULL;
hr = pUnknown->QueryInterface(__uuidof(ISimpleDevice), &pSimpleDevice);
pUnknown->Release();
pUnknown = NULL;
if (SUCCEEDED(hr))
{
// etc
pSimpleDevice->Release();
pSimpleDevice = NULL;
}
}
Code: Select all
IUnknownPtr pUnknown;
HRESULT hr = pUnknown->CreateInstance(__uuidof(Device));
if (SUCCEEDED(hr))
{
ISimpleDevicePtr pSimpleDevice = pUnknown; // This will call QueryInterface()
if (pSimpleDevice != NULL)
{
// etc
}
}
Note: I wrote the above without actually trying to compile it. There may a few "spelling" mistakes.
Hi,
thanks again for the quick response!
I resolved my issue using the following code. I hope this may help other people as well:
There is no need to call release, simply call "m_pDevice->Disconnect();" and set all the pointers to NULL.
thanks again for the quick response!
I resolved my issue using the following code. I hope this may help other people as well:
Code: Select all
ISimpleDevicePtr m_pDevice;
ISensorPtr m_p3DSensor;
IKeyboardPtr m_p3DKeyboard;
// create instance
gjBool bDeviceFound = gjFALSE;
hr = CoCreateInstance(__uuidof(Device), NULL, CLSCTX_ALL, __uuidof(ISimpleDevice), (void**)&m_pDevice);
if (SUCCEEDED(hr))
{
m_p3DSensor = m_pDevice->Sensor;
m_p3DKeyboard = m_pDevice->Keyboard;
// Connect to the driver
hr = m_pDevice->Connect();
if (SUCCEEDED(hr))
bDeviceFound = gjTRUE;
else
m_pDevice = gjNULL;
}
Ah, the eternal argument. In the end, it is a matter of style. For some, calling Release() makes the code more readable and easier to maintain.gjaegy wrote:There is no need to call release, simply call "m_pDevice->Disconnect();" and set all the pointers to NULL.
Instead of:
Code: Select all
hr = CoCreateInstance(__uuidof(Device), NULL, CLSCTX_ALL, __uuidof(ISimpleDevice), (void**)&m_pDevice);
Code: Select all
hr = m_pDevice.CreateInstance(__uuidof(Device));
Last edited by ngomes on Wed Mar 28, 2007 8:42 am, edited 1 time in total.
Concerning your second remark, you are absolutely right, I have changed my code, thanks !
Concerning the first one, I got confused because in my first attempt I used plain pointers, called ->Release() and got a crash when the TDxInput.dll dll was unloaded. But with _Ptr objects you are right, it doesn't matter.
Thanks!
Concerning the first one, I got confused because in my first attempt I used plain pointers, called ->Release() and got a crash when the TDxInput.dll dll was unloaded. But with _Ptr objects you are right, it doesn't matter.
Thanks!
-
- Posts: 44
- Joined: Fri Apr 04, 2008 7:03 am
I have a doubt. In my application, I connected the SpaceNavigator, but I don't understand the reason of instruction "if (m_p3DSensor)" of the method Update ().
In my code, even if it does not happen any interaction with the device, the application enters this "if" and prints the values 0,0,0. I need to get the values of translation and rotation only when they actually occur.
I already have a main loop that controls the application. In this case, how I could use these methods in parallel without blocking the implementation of the application?
Thanks.
In my code, even if it does not happen any interaction with the device, the application enters this "if" and prints the values 0,0,0. I need to get the values of translation and rotation only when they actually occur.
I already have a main loop that controls the application. In this case, how I could use these methods in parallel without blocking the implementation of the application?
Thanks.