[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