Windows 7 and multitouch with openframeworks

Hello

Forgive me if this question sounds dumb, but I dont have much experience in C++.

So I just recently aquired a windows 7 machine with a multitouch enabled screen, and just started using Visual studio for the first time.
I’m wondering how I could get multitouch, gesture messages from windows 7 working with an OpenFrameworks application? Any hints of how I could get started on this would be greatly appreciated

thanks

Hi,

I am currently looking into interfacing with off the shelf multitouch monitors as well.

I have found that most of the monitors out there HP, Dell etc are using Nextwindow technology (is is not really multitouch since it can only detect two touch points). You can download dll-files that give you access to their multitouch api:
http://www.nextwindow.com/nextwindow-support/api.html
There is a c++ example on the page - I haven’t tried it myself yet, but I guess it should be relatively easy to use this in openframeworks.

Alternatively, someone has written a TUIO bridge - translating the touch events to TUIO events
http://nuigroup.com/forums/viewthread/4687/
This is quite a nice way of handling the touch events and makes it easy to run your apps on other TUIO hardware.

/lars

Yeah,

I just managed to get Windows 7 “native” Gesture support working in OpenFrameworks. (Haven’t tested anything yet except the “Two finger Tap” & zooming
I guess it is more of a hack though than anything else. But than, I wouldn’t consider myself a “real” or good programmer.
Anyways.

Changes:

ofConstants.h, line 42
from:

  
  
#   define _WIN32_WINNT 0x400  
  

to

  
  
#define _WIN32_WINNT 0x0601  
  

You have to do this, otherwise WM_GESTURE won’t be available. Don’t know if there are any sideEffects.

Next you have to extract the attached files into

  
 of_preRelease_v0061_vs2008_FAT\libs\openFrameworks\app\  

[attachment=1:17s8u3x7]GestureEngine.zip[/attachment:17s8u3x7]

They are taken from http://code.msdn.microsoft.com/WindowsTouch and modified.
I do not know about legal issues using this stuff though…

Next open up
ofAppGlutWindow.cpp and
add around line 4

  
  
#include "MyGestureEngine.h"  
  

as well as

  
CMyGestureEngine * gestureEnginePtr;  

below ofBaseApp * pfAppPtr (around Line 33)

next, you have to add a case statement below case WM_DESTROY:

  
	  case WM_GESTURE:  
		  //std::cout << "Gesture caught" << std::endl;  
		  return gestureEnginePtr->WndProc(hwnd, wParam, lParam);  
  

The last change to this file is around line 225 (in runAppViaInfininteLoop)

add

  
gestureEnginePtr->setAppPointer(appPtr);  

below ofAppPtr = appPtr

next, you have to adjust ofBaseApp.h

just add

  
  
		virtual void twoFingerTap(){}  
		virtual void twoFingerZoom(double dZoomFactor,const LONG lZx,const LONG lZy) {}  
  

somewhere.
You can get the changed files hier
[attachment=0:17s8u3x7]changedInOF.zip[/attachment:17s8u3x7]

At last, you have to add

  
	void twoFingerTap();  
	void twoFingerZoom(double dZoomFactor,const LONG lZx,const LONG lZy);  
  

to your testApp.h and (as you all know, I guess)

  
void testApp::twoFingerTap(){  
	std::cout << "Two Fingers Tapped in TestApp.cpp" << std::endl;  
}  
void testApp::twoFingerZoom(double dZoomFactor,const LONG lZx,const LONG lZy){  
	std::cout << "Zooming with a factor of " << dZoomFactor << std::endl;  
}  

That’s it. – Doesn’t seem that difficult now. ^^
As I said, it is far from being done and ready, however I heard “post early, post often” is the way to go :wink:
What I especially like about this solution is, that it just blends into of seamlessly.
I wouldn’t now how to make an ofx… Extension out of it.

PS: Just tested on one machine,
HP TouchSmart IQ820 with 64Bit Windows 7. It should work in 32 Bit windows 7 as well. (Not earlier Version, as WM_GESTURE then)

http://img188.imageshack.us/img188/3227/zoomandtap.png

GestureEngine.zip

changedInOF.zip

Hey guys thanks for the replies

Im currently using a sony Vaio L-series. Ill need to dig around and find our what drivers Im using. Ill let you know of any progress I make after I investigater these options

thanks!

just some more fragments from me:

ofConstants.h

  
define _WIN32_WINNT 0x0601  

ofAppGlutWindow.cpp

  
#include "MyTouchEngine.h"  

  
MyTouchEngine * touchEnginePtr;  

in ofAppGlutWindow::ofAppGlutWindow()

  
touchEnginePtr = new MyTouchEngine(0);  

in ofAppGlutWindow::initializeWindow(

  
		// test for touch  
int value = GetSystemMetrics(SM_DIGITIZER);  
if (value & NID_READY){ /* stack ready */}  
if (value  & NID_MULTI_INPUT){  
    /* digitizer is multitouch */   
    //MessageBoxW(handle, L"Multitouch found", L"IsMulti!", MB_OK);  
	RegisterTouchWindow(handle, 0);  
} else MessageBoxW(handle, L"No Multitouch found", L"not good", MB_OK);  
if (value & NID_INTEGRATED_TOUCH){ /* Integrated touch */}  

in ofAppGlutWindow::runAppViaInfiniteLoop(ofBaseApp * appPtr)

  
touchEnginePtr->setAppPointer(appPtr);  

in LRESULT CALLBACK winProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)

  
case WM_TOUCH:  
		 return touchEnginePtr->processTouch(hwnd, wParam, lParam);  
         break;  

MyTouchEngine.h

  
#pragma once  
  
#include "ofBaseApp.h"  
  
class MyTouchEngine{  
  
public:  
    MyTouchEngine(ofBaseApp* ofAppPtr);  
    ~MyTouchEngine(void);  
  
	virtual void OnTouchDown(int id, int x, int y);  
	virtual void OnTouchMove(int id, int x, int y);  
	virtual void OnTouchUp(int id, int x, int y);  
  
	LRESULT processTouch(HWND hWnd, WPARAM wParam, LPARAM lParam);  
  
	void setAppPointer(ofBaseApp * ofAppPtr);  
	  
private:  
    ofBaseApp * _ofAppPtr;  
};  
  

MyTouchEngine.cpp

  
  
#include "MyTouchEngine.h"  
#include "ofEvents.h"  
#include "ofAppRunner.h"  
  
MyTouchEngine::MyTouchEngine(ofBaseApp * ofAppPtr){}  
  
MyTouchEngine::~MyTouchEngine(void) {}  
  
  
LRESULT MyTouchEngine::processTouch(HWND hWnd, WPARAM wParam, LPARAM lParam) {  
  
	BOOL bHandled = FALSE;  
    UINT cInputs = LOWORD(wParam);  
    PTOUCHINPUT pInputs = new TOUCHINPUT[cInputs];  
    if (pInputs){  
        if (GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT))){  
            for (UINT i=0; i < cInputs; i++){  
                TOUCHINPUT ti = pInputs[i];  
                //do something with each touch input entry  
				if (ti.dwFlags & TOUCHEVENTF_DOWN){   
					  
					OnTouchDown(ti.dwID, TOUCH_COORD_TO_PIXEL(ti.x)-ofGetWindowPositionX(), TOUCH_COORD_TO_PIXEL(ti.y)-ofGetWindowPositionY());  
				}  
				else if (ti.dwFlags & TOUCHEVENTF_MOVE){   
					  
					OnTouchMove(ti.dwID, TOUCH_COORD_TO_PIXEL(ti.x)-ofGetWindowPositionX(), TOUCH_COORD_TO_PIXEL(ti.y)-ofGetWindowPositionY());  
				}  
				if (ti.dwFlags & TOUCHEVENTF_UP){   
					  
					OnTouchUp(ti.dwID, TOUCH_COORD_TO_PIXEL(ti.x)-ofGetWindowPositionX(), TOUCH_COORD_TO_PIXEL(ti.y)-ofGetWindowPositionY());  
				}  
            }              
            bHandled = TRUE;  
        }else{  
             /* handle the error here */  
        }  
        delete [] pInputs;  
    }else{  
        /* handle the error here, probably out of memory */  
    }  
    if (bHandled){  
        // if you handled the message, close the touch input handle and return  
        CloseTouchInputHandle((HTOUCHINPUT)lParam);  
        return 0;  
    }else{  
        // if you didn't handle the message, let DefWindowProc handle it  
        return DefWindowProc(hWnd, WM_TOUCH, wParam, lParam);  
    }  
  
}  
  
void MyTouchEngine::OnTouchDown(int id, int x, int y) {  
     
	static ofTouchEventArgs touchEventArgs;  
	  
	if(_ofAppPtr) {  
  
		_ofAppPtr->touchDown(id, x, y);  
		#ifdef OF_USING_POCO  
			touchEventArgs.x = x;  
			touchEventArgs.y = y;  
			touchEventArgs.id = id;  
			ofNotifyEvent( ofEvents.touchDown, touchEventArgs );  
		#endif  
    }  
}  
  
void MyTouchEngine::OnTouchMove(int id, int x, int y) {  
      
	static ofTouchEventArgs touchEventArgs;  
  
	if(_ofAppPtr) {  
  
		_ofAppPtr->touchMove(id, x, y);  
		#ifdef OF_USING_POCO  
			touchEventArgs.x = x;  
			touchEventArgs.y = y;  
			touchEventArgs.id = id;  
			ofNotifyEvent( ofEvents.touchMoved, touchEventArgs );  
		#endif  
    }  
}  
  
void MyTouchEngine::OnTouchUp(int id, int x, int y) {  
      
	static ofTouchEventArgs touchEventArgs;  
  
	if(_ofAppPtr) {  
  
		_ofAppPtr->touchUp(id, x, y);  
		#ifdef OF_USING_POCO  
			touchEventArgs.x = x;  
			touchEventArgs.y = y;  
			touchEventArgs.id = id;  
			ofNotifyEvent( ofEvents.touchUp, touchEventArgs );  
		#endif  
    }  
}  
  
void MyTouchEngine::setAppPointer(ofBaseApp * ofAppPtr){  
	_ofAppPtr = ofAppPtr;  
}  

add to ofBaseApp.h

  
virtual void touchDown(int id, int x, int y){}  
		virtual void touchMove(int id, int x, int y){}  
		virtual void touchUp(int id, int x, int y){}  

also in testApp.h & testApp.cpp

  
void touchDown(int id, int x, int y);  
		void touchMove(int id, int x, int y);  
		void touchUp(int id, int x, int y);  

compile against windows sdk 7 (use vs 2010)

greetings ascorbin

Hey,
i tried your code (ascorbin and Richy), but i get linker errors regarding the new classes (MyTouchEngine or GestureEngine) like:

error LNK2019: unresolved external symbol “public: void __thiscall MyTouchEngine::setAppPointer(class ofBaseApp *)” (?setAppPointer@MyTouchEngine@@QAEXPAVofBaseApp@@@Z) referenced in function “public: virtual void __thiscall ofAppGlutWindow::runAppViaInfiniteLoop(class ofBaseApp *)” (?runAppViaInfiniteLoop@ofAppGlutWindow@@UAEXPAVofBaseApp@@@Z)

I’m using Windows 7 and HP TouchSmart tm2 2150ep, OF v0.062 and VS2010. Any hints?

@kazpar

hm, … not sure… place MyTouchEngine near ofAppGlutWindow, also drag it into the OF-project, clean everything, recompile…

greetings ascorbin

Thanks! i missed the “drag it into the OF-project”. It works now.

Btw, Richy you forgot to include in the post the initialization of the variable in ofAppGlutWindow constructor:

  
gestureEnginePtr = new CMyGestureEngine(0);  

Hey ascorbin + richy, nice work on getting this stuff together! Super helpful.

I ended up wrapping up your work into separate classes so you don’t have to edit the lower-level OF stuff. Only a few minor tweaks from the code you posted, hope it will be a simpler way for people to get Win7 stuff working with OF (0071 tested). Will credit you once I get the readme up and stuff like that!

Check it out:
https://github.com/labatrockwell/ofxWin7