[osg-users] Intercepting Windows messages

Anders Backman andersb at cs.umu.se
Fri Nov 13 08:04:54 PST 2015


It seems to me that OSG eats the 3DConnexion messages, until you move the
window explicitly with the mouse.
The code below show that a console window works just fine, all messages are
intercepted by the "message window".
However, when a osgViewer run loop is being used, the messages seem to be
filtered.

I only get a Spaceball event when I move the window(!).


#include <osgViewer/Viewer>
#include <osgViewer/api/Win32/GraphicsWindowWin32>

#include <iostream>


#pragma comment(lib, "siapp.lib")

#include"windows.h"
#include <iostream>

#include "spwmacro.h"  /* Common macros used by SpaceWare functions. */
#include "si.h"        /* Required for any SpaceWare support within an
app.*/
#include "siapp.h"     /* Required for siapp.lib symbols */

#pragma warning(disable:4700)

SiHdl       devHdl;       /* Handle to 3D Mouse Device */
SiOpenData oData;
WNDPROC wndProcOrig;

void ClearScreen() {
  for (unsigned i = 0; i<100; ++i) std::cout << std::endl;
}

int SbInit(HWND hwndC);
void  SbMotionEvent(SiSpwEvent *pEvent);
void  SbZeroEvent();
void  SbButtonPressEvent(int buttonnumber);
void  SbButtonReleaseEvent(int buttonnumber);
void  HandleDeviceChangeEvent(SiSpwEvent *pEvent);


LRESULT CALLBACK MyWndCBProc(
  HWND hwnd, UINT wm, WPARAM wParam, LPARAM lParam)
{
  SiSpwEvent     Event;    /* SpaceWare Event */
  SiGetEventData EData;    /* SpaceWare Event Data */

  /* initialize Window platform specific data for a call to SiGetEvent */
  SiGetEventWinInit(&EData, wm, wParam, lParam);

  /* check whether wm was a 3D mouse event and process it */
  //if (SiGetEvent (devHdl, SI_AVERAGE_EVENTS, &EData, &Event) ==
SI_IS_EVENT)
  SpwRetVal retval = SiGetEvent(devHdl, 0, &EData, &Event);

  if (retval == SI_IS_EVENT)
  {
    if (Event.type == SI_MOTION_EVENT)
    {
      SbMotionEvent(&Event);        /* process 3D mouse motion event */
    }
    else if (Event.type == SI_ZERO_EVENT)
    {
      SbZeroEvent();                /* process 3D mouse zero event */
    }
    else if (Event.type == SI_BUTTON_PRESS_EVENT)
    {
      SbButtonPressEvent(Event.u.hwButtonEvent.buttonNumber);  /* process
button press event */
    }
    else if (Event.type == SI_BUTTON_RELEASE_EVENT)
    {
      SbButtonReleaseEvent(Event.u.hwButtonEvent.buttonNumber); /* process
button release event */
    }
    else if (Event.type == SI_DEVICE_CHANGE_EVENT)
    {
      //SbHandleDeviceChangeEvent(&Event); /* process 3D mouse device
change event */
    }
  }

  return DefWindowProc(hwnd, wm, wParam, lParam);
}

void mainx(void) {


  /* Implement message loop */
  int bRet;
  MSG msg;      /* incoming message to be evaluated */
  while (bRet = GetMessage(&msg, NULL, 0, 0))
  {
    if (bRet == -1){
      /* handle the error and possibly exit */
      return;
    }
    else{
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }
}


int SbInit(HWND hwndC)
{
  int res;                             /* result of SiOpen, to be returned
 */

  /*init the SpaceWare input library */
  if (SiInitialize() == SPW_DLL_LOAD_ERROR)  {
    std::cout << "Error: Could not load SiAppDll dll files" << std::endl;
  }
  else {
    //std::cout << "SiInitialize() done " << std::endl;
  }

  SiOpenWinInit(&oData, hwndC);    /* init Win. platform specific data  */

  /* open data, which will check for device type and return the device
handle to be used by this function */
  if ((devHdl = SiOpen("AppSpaceMouse.exe", SI_ANY_DEVICE, SI_NO_MASK,
SI_EVENT, &oData)) == NULL) {
    std::cout << "SiOpen error:" << std::endl;
    SiTerminate();  /* called to shut down the SpaceWare input library */
    std::cout << "SiTerminate()" << std::endl;
    res = 0;        /* could not open device */
    return res;
  }

  SiDeviceName pname;
  SiGetDeviceName(devHdl, &pname);
  //std::cout << "devicename =  " << pname.name << std::endl;

  SiSetUiMode(devHdl, SI_UI_ALL_CONTROLS); /* Config SoftButton Win Display
*/
  SiGrabDevice(devHdl, SPW_TRUE); /* PREVENTS OTHER APPLICATIONS FROM
RECEIVING 3D CONNEXION DATA !!! */
  res = 1;        /* opened device succesfully */
  return res;
}

void  SbMotionEvent(SiSpwEvent *pEvent) {
  std::cout << "TX=" << pEvent->u.spwData.mData[SI_TX] << " TY=" <<
pEvent->u.spwData.mData[SI_TY] << " TZ=" << pEvent->u.spwData.mData[SI_TZ]
<< " RX=" << pEvent->u.spwData.mData[SI_RX] << " RY=" <<
pEvent->u.spwData.mData[SI_RY] << " RZ=" << pEvent->u.spwData.mData[SI_RZ]
<< std::endl;
}
void  SbZeroEvent() {
  std::cout << "zeroevent: " << std::endl;
}
void  SbButtonPressEvent(int buttonnumber) {
  std::cout << "Buttonnumber : " << buttonnumber << std::endl;
}
void  SbButtonReleaseEvent(int buttonnumber) {
  std::cout << "Buttonnumber : " << buttonnumber << std::endl;
}
void  HandleDeviceChangeEvent(SiSpwEvent *pEvent) {
  std::cout << "HandleDeviceChangeEvent : " << std::endl;

}


int main(int argc, char** argv)
{
  osg::ArgumentParser arguments(&argc, argv);
#if 1
  osgViewer::Viewer viewer(arguments);
#else
  osgViewer::CompositeViewer viewer(arguments);

  osgViewer::View* view = new osgViewer::View;
  view->setName("View one");
  viewer.addView(view);

  view->setSceneData(scene.get());
  view->getCamera()->setName("Cam one");
  view->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width / 2,
traits->height / 2));
  view->getCamera()->setGraphicsContext(gc.get());

#endif



    viewer.realize();

    osgViewer::Viewer::Windows windows;
    viewer.getWindows(windows);

    osgViewer::GraphicsWindow* window = windows[0];
    window->setWindowRectangle(40, 40,1024,768);
    window->setWindowDecoration(true);




    /* Retrieve console application main window using GetConsoleWindow() */
    //HWND windowHandle = GetConsoleWindow(); /* Great!!  This function
 cleverly "retrieves the window handle  used by the console associated with
the calling process",   as msdn says */

    /* Register a custom window class */
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = MyWndCBProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = GetModuleHandle(NULL);
    wcex.hIcon = NULL;
    wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = "MyWindowClassName";
    wcex.hIconSm = NULL;
    RegisterClassEx(&wcex);

    /* Create a hidden window owned by our process and parented to the
console window */
    HWND hWndChild = CreateWindow(wcex.lpszClassName, "MyWindowTitle",
WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, wcex.hInstance, NULL);

    /* Initialise 3DxWare access / call to SbInit() */
    SbInit(hWndChild);

#if 0
     /* Implement message loop */
  int bRet;
  MSG msg;      /* incoming message to be evaluated */
  while (bRet = GetMessage(&msg, NULL, 0, 0))
  {
    if (bRet == -1){
      /* handle the error and possibly exit */
      return 1;
    }
    else{
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }
  return 0;
#else
  return viewer.run();
#endif
}


On Fri, Nov 13, 2015 at 3:50 PM, Anders Backman <andersb at cs.umu.se> wrote:

> Ah thats great. A good step forward.
> However, two minor questions:
>
> 1. Do you need the instance to the main osg window?
> 2. If not, how do you manage to get events from the device when you apply
> force on it?
>
> I get it to read data (in my message callback) but only if a move/modify
> the osg window (Im using osgViewer::Viewer with just one window).
>
> /A
>
> On Thu, Nov 12, 2015 at 10:53 PM, Farshid Lashkari <flashk at gmail.com>
> wrote:
>
>> Hi Anders,
>>
>> You can create a separate "message-only" window to receive windows
>> messages from the SpaceMouse. See the following MSDN page:
>>
>>
>> https://msdn.microsoft.com/en-us/library/windows/desktop/ms632599(v=vs.85).aspx#message_only
>>
>> I've integrated the 3DConnexion SpaceNavigator into our application using
>> this method, along with other 3rd party APIs that require a window handle.
>>
>> Cheers,
>> Farshid
>>
>> On Thu, Nov 12, 2015 at 11:01 AM, Anders Backman <andersb at cs.umu.se>
>> wrote:
>>
>>> So there seem to be only a very few alternatives for integrating such a
>>> windows oriented toolkit as the 3DConnexion SpaceMouse...
>>>
>>> My idea of being able to create a custom implementation of a
>>> GraphicsWindowWin32 would really open up for a better integration, albeit
>>> not a portable one...
>>>
>>> Right now, using VRPN feels a bit strange in a native application (as it
>>> requires a server).
>>>
>>> As far as I know there is no polling API for the 3DConnexion devices, no?
>>>
>>> I see older emails about accessing it through Direct3D, and native
>>> USB...whereas listening to windows messages would be the "correct" way of
>>> integrating it.
>>> I would have to hack into the context classes to do this...
>>>
>>> Hm....
>>>
>>> /Anders
>>>
>>>
>>> On Thu, Nov 12, 2015 at 3:54 PM, Anders Backman <andersb at cs.umu.se>
>>> wrote:
>>>
>>>> That is certainly an important call yes.
>>>>
>>>> I guess my problem is that these two calls are not interchangeable:
>>>>
>>>> #if 1
>>>>     osg::ref_ptr<osg::GraphicsContext> gc =
>>>> osg::GraphicsContext::createGraphicsContext(traits.get());
>>>> #else
>>>>     osg::ref_ptr<osgViewer::GraphicsWindowWin32> window = new
>>>> osgViewer::GraphicsWindowWin32(traits);
>>>>     gc = window.get();
>>>> #endif
>>>>
>>>> createGraphicsContext() will do a few more things which the creation of
>>>> a osgViewer::GraphicsWindowWin32 does not. The question is really, is it
>>>> possible to even consider this?
>>>> Is there a mechanism for creating a custom GraphicsWindowWin32 or is
>>>> this path doomed to fail.
>>>>
>>>> /Anders
>>>>
>>>>
>>>>
>>>> On Thu, Nov 12, 2015 at 3:31 PM, Trajce Nikolov NICK <
>>>> trajce.nikolov.nick at gmail.com> wrote:
>>>>
>>>>> Did you tried something like:
>>>>>
>>>>> osgViewer::Viewer viewer;
>>>>> viewer.getCamera()->setGraphicContext(gc);
>>>>>
>>>>> ?
>>>>>
>>>>> On Thu, Nov 12, 2015 at 2:52 PM, Anders Backman <andersb at cs.umu.se>
>>>>> wrote:
>>>>>
>>>>>> I notice that there is a major difference between osgViewer::Viewer
>>>>>> and osgViewer::CompositeViewer:
>>>>>>
>>>>>> The following code:
>>>>>>
>>>>>> osgViewer::CompositeViewer viewer;
>>>>>>
>>>>>>  osg::ref_ptr<osg::GraphicsContext::Traits> traits = new
>>>>>> osg::GraphicsContext::Traits;
>>>>>>     traits->x = 100;
>>>>>>     traits->y = 100;
>>>>>>     traits->width = 1000;
>>>>>>     traits->height = 800;
>>>>>>     traits->windowDecoration = true;
>>>>>>     traits->doubleBuffer = true;
>>>>>>     traits->sharedContext = 0;
>>>>>>
>>>>>>     osg::ref_ptr<osg::GraphicsContext> gc =
>>>>>> osg::GraphicsContext::createGraphicsContext(traits.get());
>>>>>>
>>>>>>    osgViewer::View* view = new osgViewer::View;
>>>>>>     view->setName("View one");
>>>>>>     viewer.addView(view);
>>>>>>
>>>>>>     view->setSceneData(scene.get());
>>>>>>     view->getCamera()->setViewport(new osg::Viewport(0, 0,
>>>>>> traits->width / 2, traits->height / 2));
>>>>>>     view->getCamera()->setGraphicsContext(gc.get());
>>>>>>
>>>>>>     viewer.realize(); // Context already created. No call to
>>>>>> GraphicsWIndowWIn32::GraphicsWIndowWin32 will be called
>>>>>>
>>>>>>
>>>>>>
>>>>>> If I replace osgViewerCompositeViewer with a osgViewer::Viewer and
>>>>>> remove the creation of View, I get:
>>>>>>
>>>>>>     viewer.realize(); // A new context is created. A new call to
>>>>>> GraphicsWIndowWIn32::GraphicsWIndowWin32 will be called
>>>>>>
>>>>>>
>>>>>> So it seems that osgViewer::Viewer does not respect? the previously
>>>>>> created GraphicsCOntext?
>>>>>>
>>>>>> /Anders
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Thu, Nov 12, 2015 at 2:24 PM, Anders Backman <andersb at cs.umu.se>
>>>>>> wrote:
>>>>>>
>>>>>>> That is quite explicit. I was thinking about some method for
>>>>>>> intercepting events.
>>>>>>> I tried fiddling with creating a custom GraphicsWindowWin32 class,
>>>>>>> but it turns out that this is explicitly created internally in:
>>>>>>>
>>>>>>> osg::GraphicsContext* Win32WindowingSystem::createGraphicsContext(
>>>>>>> osg::GraphicsContext::Traits* traits )
>>>>>>> {
>>>>>>> ...
>>>>>>>         osg::ref_ptr<osgViewer::GraphicsWindowWin32> window = new
>>>>>>> GraphicsWindowWin32(traits);
>>>>>>>
>>>>>>> }
>>>>>>>
>>>>>>> So this does not seem to be the way to catch windows messages.
>>>>>>> My idea was that I could register my instance of the
>>>>>>> GraphicsWindowWin32 to implement the virtual method:
>>>>>>>
>>>>>>> LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd,
>>>>>>> UINT uMsg, WPARAM wParam, LPARAM lParam )
>>>>>>>
>>>>>>>
>>>>>>> Where I could catch all windows events.
>>>>>>>
>>>>>>>
>>>>>>> Turns out that I do not have enough understanding when and where
>>>>>>> context etc is created.
>>>>>>>
>>>>>>> It seems that a GraphicsWindowWIn32 is first created at the call to:
>>>>>>>
>>>>>>>     osg::ref_ptr<osg::GraphicsContext> gc =
>>>>>>> osg::GraphicsContext::createGraphicsContext(traits.get());
>>>>>>>
>>>>>>>
>>>>>>> And then at the call to:
>>>>>>>
>>>>>>> viewer->realize();
>>>>>>>
>>>>>>> will also result in a call
>>>>>>> to GraphicsContext::createGraphicsContext(Traits* traits), which in turn
>>>>>>> will create yet another GraphicsWindowWin32.
>>>>>>>
>>>>>>> So there lies my problem, my call to viewer->realize() will override
>>>>>>> my first call to GraphicsContext::createGraphicsContext(traits.get());
>>>>>>>
>>>>>>>
>>>>>>> Not sure how to get around this though. Ideas?
>>>>>>>
>>>>>>> /Anders
>>>>>>>
>>>>>>>
>>>>>>> On Wed, Nov 11, 2015 at 5:05 PM, Trajce Nikolov NICK <
>>>>>>> trajce.nikolov.nick at gmail.com> wrote:
>>>>>>>
>>>>>>>> Hi Anders,
>>>>>>>>
>>>>>>>> here is what I do for this on Windows
>>>>>>>>
>>>>>>>>     while (!viewer->done())
>>>>>>>>     {
>>>>>>>>
>>>>>>>> #if defined(_WIN32)
>>>>>>>>         MSG msg;
>>>>>>>>         if (::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
>>>>>>>>         {
>>>>>>>>             ::GetMessage(&msg, NULL, 0, 0);
>>>>>>>>
>>>>>>>>             if (wins.size())
>>>>>>>>             {
>>>>>>>>                 osgViewer::GraphicsHandleWin32 *hdl =
>>>>>>>> dynamic_cast<osgViewer::GraphicsHandleWin32*>(wins.at(0));
>>>>>>>>                 if(hdl)
>>>>>>>>                 {
>>>>>>>>                     WNDPROC fWndProc =
>>>>>>>> (WNDPROC)::GetWindowLongPtr(hdl->getHWND(), GWLP_WNDPROC);
>>>>>>>>                     if (fWndProc && hdl->getHWND())
>>>>>>>> {
>>>>>>>> ::CallWindowProc(fWndProc,hdl->getHWND(),msg.message, msg.wParam,
>>>>>>>> msg.lParam);
>>>>>>>> }
>>>>>>>>                 }
>>>>>>>>             }
>>>>>>>>         }
>>>>>>>> #endif
>>>>>>>>
>>>>>>>> On Wed, Nov 11, 2015 at 4:21 PM, Anders Backman <andersb at cs.umu.se>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> Hi.
>>>>>>>>>
>>>>>>>>> Trying the 3DConnexion SpaceNavigator with OSG. However I would
>>>>>>>>> like to stay away from VRPN and such dependencies...
>>>>>>>>>
>>>>>>>>> I was wondering how to best intercept Windows messages from the
>>>>>>>>> GraphicsWindowWin32 class.
>>>>>>>>>
>>>>>>>>> This class has a virtual method handleNativeWindowingEvent which I
>>>>>>>>> would like to override to catch custom messages from my device.
>>>>>>>>>
>>>>>>>>> Would it be possible to implement a derived class and have that
>>>>>>>>> instantiated instead of the standard osgViewer::GraphicsWindowWin32 one?
>>>>>>>>>
>>>>>>>>> Or is there a different method to listen to the  messages:
>>>>>>>>>
>>>>>>>>> ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>> Anders
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> __________________________________________
>>>>>>>>> Anders Backman, HPC2N
>>>>>>>>> 90187 Umeå University, Sweden
>>>>>>>>> anders at cs.umu.se http://www.hpc2n.umu.se
>>>>>>>>> Cell: +46-70-392 64 67
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> osg-users mailing list
>>>>>>>>> osg-users at lists.openscenegraph.org
>>>>>>>>>
>>>>>>>>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> --
>>>>>>>> trajce nikolov nick
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> osg-users mailing list
>>>>>>>> osg-users at lists.openscenegraph.org
>>>>>>>>
>>>>>>>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> __________________________________________
>>>>>>> Anders Backman, HPC2N
>>>>>>> 90187 Umeå University, Sweden
>>>>>>> anders at cs.umu.se http://www.hpc2n.umu.se
>>>>>>> Cell: +46-70-392 64 67
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> __________________________________________
>>>>>> Anders Backman, HPC2N
>>>>>> 90187 Umeå University, Sweden
>>>>>> anders at cs.umu.se http://www.hpc2n.umu.se
>>>>>> Cell: +46-70-392 64 67
>>>>>>
>>>>>> _______________________________________________
>>>>>> osg-users mailing list
>>>>>> osg-users at lists.openscenegraph.org
>>>>>>
>>>>>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> trajce nikolov nick
>>>>>
>>>>> _______________________________________________
>>>>> osg-users mailing list
>>>>> osg-users at lists.openscenegraph.org
>>>>>
>>>>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> __________________________________________
>>>> Anders Backman, HPC2N
>>>> 90187 Umeå University, Sweden
>>>> anders at cs.umu.se http://www.hpc2n.umu.se
>>>> Cell: +46-70-392 64 67
>>>>
>>>
>>>
>>>
>>> --
>>> __________________________________________
>>> Anders Backman, HPC2N
>>> 90187 Umeå University, Sweden
>>> anders at cs.umu.se http://www.hpc2n.umu.se
>>> Cell: +46-70-392 64 67
>>>
>>> _______________________________________________
>>> osg-users mailing list
>>> osg-users at lists.openscenegraph.org
>>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>>
>>>
>>
>> _______________________________________________
>> osg-users mailing list
>> osg-users at lists.openscenegraph.org
>> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>>
>>
>
>
> --
> __________________________________________
> Anders Backman, HPC2N
> 90187 Umeå University, Sweden
> anders at cs.umu.se http://www.hpc2n.umu.se
> Cell: +46-70-392 64 67
>



-- 
__________________________________________
Anders Backman, HPC2N
90187 Umeå University, Sweden
anders at cs.umu.se http://www.hpc2n.umu.se
Cell: +46-70-392 64 67
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openscenegraph.org/pipermail/osg-users-openscenegraph.org/attachments/20151113/f630333b/attachment-0003.htm>


More information about the osg-users mailing list