we've been using the 3d mouse in our project for quite some time, and now a new requirement has come up by which we need to be able to control our 3D view even when the application doesn't have th focus. So when some other GUI has the focus and we operate the 3D mouse, we still need the input from the 3d mouse to be send to our 3d application, if that makes sense. The GUI is not full screen but it will most of the time be on top of the 3d application and have the focus most of the time.
I'm not a winapi wizard but my research showed that if I want to do this, I need to make a DLL where I put the hook function so that I can catch the windows messages on a global scope. That is if I do
SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)MessageHookCB, GetModuleHandle(NULL), NULL)
it will not work, we need to have this MessageHookCB in a new DLL. Fine, let's do that then.
First of all, we are basically making a plugin for some 3d engine, this plugin is a DLL and essentially what we were doing before was something like this:
Code: Select all
bool vrvSpaceMouseDevice::Init(HWND a_hwnd, std::string& a_initResultMessage)
{
// init the 3DxWare input library
if (SiInitialize() == SPW_DLL_LOAD_ERROR)
{
a_initResultMessage = "Space Mouse initialization error ! Are you sure drivers are installed ?";
return false;
}
// Init Windows platform specific data
SiOpenWinInit(&m_oData, a_hwnd);
// Open data, which will check for device type and return the device handle to be used by this function
m_hdl = SiOpen("3DxStealth", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &m_oData);
if (m_hdl == NULL)
{
a_initResultMessage = "Space Mouse opening error ! Are you sure device is connected ? ";
SiTerminate(); // Shut down the SpaceWare input library
return false;
}
else
{
m_bSpaceMouseFound = true;
}
// Attach Windows Message Pump Hook Callback.
if (SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)MessageHookCB, GetModuleHandle(NULL), GetCurrentThreadId()) == NULL)
{
a_initResultMessage = "Space Mouse handling error : Unable to setup Message Hook Callback !";
SiTerminate(); // Shut down the SpaceWare input library
return false;
}
a_initResultMessage = "Space Mouse Initialization successful";
return true;
}
Code: Select all
void vrvSpaceMouseDevice::HandleWindowsMessage(MSG* a_lpmsg)
{
SiSpwEvent Event; // SpaceWare Event
SiGetEventData eData; // SpaceWare Event Data
// init Window platform specific data for a call to SiGetEvent
SiGetEventWinInit(&eData, a_lpmsg->message, a_lpmsg->wParam, a_lpmsg->lParam);
// check whether msg was a 3D mouse event and process it
if (SiGetEvent(m_hdl, 0, &eData, &Event) == SI_IS_EVENT)
{
// Axis Motion events
if (Event.type == SI_MOTION_EVENT)
{
m_SpaceMouseData.setAxisData(0, Event.u.spwData.mData[SI_TX] / m_fMaxAxisValue);
m_SpaceMouseData.setAxisData(1, Event.u.spwData.mData[SI_TY] / m_fMaxAxisValue);
m_SpaceMouseData.setAxisData(2, Event.u.spwData.mData[SI_TZ] / m_fMaxAxisValue);
m_SpaceMouseData.setAxisData(3, Event.u.spwData.mData[SI_RX] / m_fMaxAxisValue);
m_SpaceMouseData.setAxisData(4, Event.u.spwData.mData[SI_RY] / m_fMaxAxisValue);
m_SpaceMouseData.setAxisData(5, Event.u.spwData.mData[SI_RZ] / m_fMaxAxisValue);
}
if (Event.type == SI_ZERO_EVENT)
{
m_SpaceMouseData.setAxisData(0, 0);
m_SpaceMouseData.setAxisData(1, 0);
m_SpaceMouseData.setAxisData(2, 0);
m_SpaceMouseData.setAxisData(3, 0);
m_SpaceMouseData.setAxisData(4, 0);
m_SpaceMouseData.setAxisData(5, 0);
}
// Button Events
if (Event.type == SI_BUTTON_EVENT)
{
int num; // number of button pressed
if ((num = SiButtonPressed(&Event)) != SI_NO_BUTTON)
{
switch (num)
{
case V3DK_MENU:
m_SpaceMouseData.setButtonData(0, true);
break;
case V3DK_FIT:
m_SpaceMouseData.setButtonData(1, true);
break;
default:
break;
}
}
if ((num = SiButtonReleased(&Event)) != SI_NO_BUTTON)
{
switch (num)
{
case V3DK_MENU:
m_SpaceMouseData.setButtonData(0, false);
break;
case V3DK_FIT:
m_SpaceMouseData.setButtonData(1, false);
break;
default:
break;
}
}
}
// Disconnection event
if (Event.type == SI_DEVICE_CHANGE_EVENT)
{
switch (Event.u.deviceChangeEventData.type)
{
case SI_DEVICE_CHANGE_CONNECT:
break;
case SI_DEVICE_CHANGE_DISCONNECT:
m_SpaceMouseData.setAxisData(0, 0);
m_SpaceMouseData.setAxisData(1, 0);
m_SpaceMouseData.setAxisData(2, 0);
m_SpaceMouseData.setAxisData(3, 0);
m_SpaceMouseData.setAxisData(4, 0);
m_SpaceMouseData.setAxisData(5, 0);
break;
default:
break;
}
}
}
}
Code: Select all
static float GetTx() { return m_SpaceMouseData.getAxisData(0); }
static float GetTy() { return m_SpaceMouseData.getAxisData(1); }
static float GetTz() { return m_SpaceMouseData.getAxisData(2); }
static float GetRx() { return m_SpaceMouseData.getAxisData(3); }
static float GetRy() { return m_SpaceMouseData.getAxisData(4); }
static float GetRz() { return m_SpaceMouseData.getAxisData(5); }
and in our plugin, do something like this: (removed error checking for simplicity's sake)
Code: Select all
HWND hdll = LoadLibrary("3dmouse.dll");
DefaultProc initProc = (DefaultProc)GetProcAddress(hDll, "init");
initProc();
LPGetMsgProc pfnProc = (LPGetMsgProc)GetProcAddress(hDll, "GetMsgProc");
HHOOK hHook = SetWindowsHookEx(WH_GETMESSAGE, pfnProc, hDll, 0);
m_hdl = SiOpen("3DxStealth", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &m_oData);
I'm not very familiar with the 3DxWareSDK, this was implemented by someone else in the past, who no longer works for us. So all I know is that m_hdl is NULL but I don't know why this is happening. The exact same code was working fine when I was calling it from the plugin's dll.
any idea what could be going wrong here?
Cheers,
Thomas