Selaa lähdekoodia

support horizontal and vertical panning touch gestures

sabrogden 6 vuotta sitten
vanhempi
sitoutus
a9d3098475
4 muutettua tiedostoa jossa 229 lisäystä ja 1 poistoa
  1. 168 0
      ImageViewer.cpp
  2. 7 0
      ImageViewer.h
  3. 52 1
      ScrollHelper.cpp
  4. 2 0
      ScrollHelper.h

+ 168 - 0
ImageViewer.cpp

@@ -35,6 +35,8 @@ BEGIN_MESSAGE_MAP(CImageViewer, CWnd)
 	ON_WM_LBUTTONUP()
 	ON_WM_MOUSEHWHEEL()
 	ON_WM_ERASEBKGND()
+	ON_MESSAGE(WM_GESTURE, &CImageViewer::OnGesture)
+	ON_MESSAGE(WM_GESTURENOTIFY, &CImageViewer::OnGestureNotify)
 END_MESSAGE_MAP()
 
 BOOL CImageViewer::Create(CWnd* pParent)
@@ -164,22 +166,27 @@ void CImageViewer::OnPaint()
 
 void CImageViewer::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
 {
+	//OutputDebugString(_T("OnHScroll\r\n"));
 	m_scrollHelper.OnHScroll(nSBCode, nPos, pScrollBar);
 }
 
 void CImageViewer::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
 {
+	//OutputDebugString(_T("OnVScroll\r\n"));
 	m_scrollHelper.OnVScroll(nSBCode, nPos, pScrollBar);
 }
 
 BOOL CImageViewer::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
 {
+	//OutputDebugString(_T("OnMouseWheel\r\n"));
 	BOOL wasScrolled = m_scrollHelper.OnMouseWheel(nFlags, zDelta, pt);
 	return wasScrolled;
 }
 
 void CImageViewer::OnMouseHWheel(UINT nFlags, short zDelta, CPoint pt)
 {
+	//OutputDebugString(_T("OnMouseHWheel\r\n"));
+
 	BOOL wasScrolled = m_scrollHelper.OnMouseHWheel(nFlags, zDelta, pt);
 
 	CWnd::OnMouseHWheel(nFlags, zDelta, pt);
@@ -238,4 +245,165 @@ BOOL CImageViewer::OnEraseBkgnd(CDC* pDC)
 	return FALSE;
 }
 
+LRESULT CImageViewer::OnGesture(WPARAM wParam, LPARAM lParam)
+{
+	CPoint ptZoomCenter;
+	double k;
+	GESTUREINFO gi;
+
+	ZeroMemory(&gi, sizeof(GESTUREINFO));
+
+	gi.cbSize = sizeof(GESTUREINFO);
+
+	BOOL bResult = GetGestureInfo((HGESTUREINFO)lParam, &gi);
+	BOOL bHandled = FALSE;
+
+	if (bResult) {
+		// now interpret the gesture
+		switch (gi.dwID) {
+		case GID_ZOOM:
+			//OutputDebugString(_T("zoom\r\n"));
+			// Code for zooming goes here     
+			bHandled = TRUE;
+
+			switch (gi.dwFlags)
+			{
+			case GF_BEGIN:
+				m_dwArguments = LODWORD(gi.ullArguments);
+				m_ptFirst.x = gi.ptsLocation.x;
+				m_ptFirst.y = gi.ptsLocation.y;
+				::ScreenToClient(m_hWnd, &m_ptFirst);
+				break;
+
+			default:
+				// We read here the second point of the gesture. This is middle point between 
+				// fingers in this new position.
+				m_ptSecond.x = gi.ptsLocation.x;
+				m_ptSecond.y = gi.ptsLocation.y;
+				::ScreenToClient(m_hWnd, &m_ptSecond);
+
+				// We have to calculate zoom center point 
+				ptZoomCenter.x = (m_ptFirst.x + m_ptSecond.x) / 2;
+				ptZoomCenter.y = (m_ptFirst.y + m_ptSecond.y) / 2;
+
+				// The zoom factor is the ratio between the new and the old distance. 
+				// The new distance between two fingers is stored in gi.ullArguments 
+				// (lower DWORD) and the old distance is stored in _dwArguments.
+				k = (double)(LODWORD(gi.ullArguments)) / (double)(m_dwArguments);
+
+				// Now we process zooming in/out of the object
+				//ProcessZoom(k, ptZoomCenter.x, ptZoomCenter.y);
+
+				//m_scrollHelper.Update(ptZoomCenter);
+
+				//CString cs;
+				//cs.Format(_T("ZOOM k: %f, x: %d, y: %d\r\n"), k, ptZoomCenter.x, ptZoomCenter.y);
+				//OutputDebugString(cs);
+
+				//InvalidateRect(hWnd, NULL, TRUE);
+
+				// Now we have to store new information as a starting information 
+				// for the next step in this gesture.
+				m_ptFirst = m_ptSecond;
+				m_dwArguments = LODWORD(gi.ullArguments);
+				break;
+			}
+			break;
+		case GID_PAN:
+			//OutputDebugString(_T("pan\r\n"));
+			// Code for panning goes here
+			bHandled = TRUE;
+			switch (gi.dwFlags)
+			{
+			case GF_BEGIN:
+				m_ptFirst.x = gi.ptsLocation.x;
+				m_ptFirst.y = gi.ptsLocation.y;
+				::ScreenToClient(m_hWnd, &m_ptFirst);
+				break;
+
+			default:
+				// We read the second point of this gesture. It is a middle point
+				// between fingers in this new position
+				m_ptSecond.x = gi.ptsLocation.x;
+				m_ptSecond.y = gi.ptsLocation.y;
+				::ScreenToClient(m_hWnd, &m_ptSecond);
+
+				int xDiff = m_ptSecond.x - m_ptFirst.x;
+
+				int yDiff = m_ptSecond.y - m_ptFirst.y;
+
+				m_scrollHelper.Update(CPoint(-xDiff, -yDiff));
+
+				//CString cs;
+				//cs.Format(_T("x: %d, y: %d\r\n"), xDiff, yDiff);
+				//OutputDebugString(cs);
+
+				// We apply move operation of the object
+				//ProcessMove(_ptSecond.x - _ptFirst.x, _ptSecond.y - _ptFirst.y);
 
+				//InvalidateRect(hWnd, NULL, TRUE);
+
+				// We have to copy second point into first one to prepare
+				// for the next step of this gesture.
+				m_ptFirst = m_ptSecond;
+				break;
+			}
+
+			break;
+			break;
+		case GID_ROTATE:
+			//OutputDebugString(_T("rotate\r\n"));
+			// Code for rotation goes here
+			bHandled = TRUE;
+			break;
+		case GID_TWOFINGERTAP:
+			//OutputDebugString(_T("two finger\r\n"));
+			// Code for two-finger tap goes here
+			bHandled = TRUE;
+			break;
+		case GID_PRESSANDTAP:
+			//OutputDebugString(_T("press and tap\r\n"));
+			// Code for roll over goes here
+			bHandled = TRUE;
+			break;
+		default:
+			// A gesture was not recognized
+			break;
+		}
+	}
+	else {
+		DWORD dwErr = GetLastError();
+		if (dwErr > 0) {
+			//MessageBoxW(hWnd, L"Error!", L"Could not retrieve a GESTUREINFO structure.", MB_OK);
+		}
+	}
+
+	return FALSE;
+}
+
+LRESULT CImageViewer::OnGestureNotify(WPARAM wParam, LPARAM lParam)
+{
+	// This is the right place to define the list of gestures that this
+			// application will support. By populating GESTURECONFIG structure 
+			// and calling SetGestureConfig function. We can choose gestures 
+			// that we want to handle in our application. In this app we
+			// decide to handle all gestures.
+	GESTURECONFIG gc = {
+		GID_PAN,              // gesture ID
+		GC_PAN | GC_PAN_WITH_SINGLE_FINGER_VERTICALLY | GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY | GC_PAN_WITH_GUTTER | GC_PAN_WITH_INERTIA, // settings related to gesture ID that are to be 
+						// turned on
+		0               // settings related to gesture ID that are to be 
+						// turned off
+	};
+
+	BOOL bResult = ::SetGestureConfig(
+		m_hWnd,                 // window for which configuration is specified  
+		0,                    // reserved, must be 0
+		1,                    // count of GESTURECONFIG structures
+		&gc,                  // array of GESTURECONFIG structures, dwIDs will be processed in the
+							  // order specified and repeated occurances will overwrite previous ones
+		sizeof(GESTURECONFIG) // sizeof(GESTURECONFIG)
+	);
+
+	return TRUE;
+}

+ 7 - 0
ImageViewer.h

@@ -22,6 +22,11 @@ public:
 
 	bool m_hoveringOverImage;
 
+
+	CPoint m_ptFirst;
+	CPoint m_ptSecond;
+	DWORD m_dwArguments;
+
 protected:
 	DECLARE_MESSAGE_MAP()
 
@@ -35,6 +40,8 @@ public:
 	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
 	afx_msg void OnMouseHWheel(UINT nFlags, short zDelta, CPoint pt);
 	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+	afx_msg LRESULT OnGesture(WPARAM wParam, LPARAM lParam);
+	afx_msg LRESULT OnGestureNotify(WPARAM wParam, LPARAM lParam);
 };
 
 

+ 52 - 1
ScrollHelper.cpp

@@ -251,6 +251,57 @@ void CScrollHelper::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
     }
 }
 
+BOOL CScrollHelper::Update(CPoint changes)
+{
+	int deltaYPos = changes.y;
+
+	int newYScrollPos = m_scrollPos.cy + deltaYPos;
+
+	// If the new scroll position is negative, we adjust
+	// deltaPos in order to scroll the window back to origin.
+	if (newYScrollPos < 0)
+		deltaYPos = -m_scrollPos.cy;
+
+	// If the new scroll position is greater than the max scroll position,
+	// we adjust deltaPos in order to scroll the window precisely to the
+	// maximum position.
+	int maxYScrollPos = m_displaySize.cy - m_pageSize.cy;
+	if (newYScrollPos > maxYScrollPos)
+		deltaYPos = maxYScrollPos - m_scrollPos.cy;
+
+	if (changes.y != 0)
+	{
+		m_scrollPos.cy += deltaYPos;
+		m_attachWnd->SetScrollPos(SB_VERT, m_scrollPos.cy, TRUE);
+	}
+
+	int deltaXPos = changes.x;
+
+	int newXScrollPos = m_scrollPos.cx + deltaXPos;
+
+	// If the new scroll position is negative, we adjust
+	// deltaPos in order to scroll the window back to origin.
+	if (newXScrollPos < 0)
+		deltaXPos = -m_scrollPos.cx;
+
+	// If the new scroll position is greater than the max scroll position,
+	// we adjust deltaPos in order to scroll the window precisely to the
+	// maximum position.
+	int maxXScrollPos = m_displaySize.cx - m_pageSize.cx;
+	if (newXScrollPos > maxXScrollPos)
+		deltaXPos = maxXScrollPos - m_scrollPos.cx;
+
+	if (changes.x != 0)
+	{
+		m_scrollPos.cx += deltaXPos;
+		m_attachWnd->SetScrollPos(SB_HORZ, m_scrollPos.cx, TRUE);
+	}
+		
+	m_attachWnd->ScrollWindow(-deltaXPos, -deltaYPos);
+
+	return 1;
+}
+
 BOOL CScrollHelper::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
 {
     if ( m_attachWnd == NULL )
@@ -418,7 +469,7 @@ void CScrollHelper::UpdateScrollBar(int bar, int windowSize, int displaySize,
             scrollPos = (LONG)(1.0 * scrollPos * windowSize / pageSize);
         }
         pageSize = windowSize;
-        scrollPos = min(scrollPos, displaySize - pageSize - 1);
+		scrollPos = min(scrollPos, displaySize - pageSize - 1);
         deltaPos = m_attachWnd->GetScrollPos(bar) - scrollPos;
     }
     else

+ 2 - 0
ScrollHelper.h

@@ -43,6 +43,8 @@ public:
 	BOOL   OnMouseHWheel(UINT nFlags, short zDelta, CPoint pt);
     void   OnSize(UINT nType, int cx, int cy);
 
+	BOOL   Update(CPoint changes);
+
 private:
     int    Get32BitScrollPos(int bar, CScrollBar* pScrollBar);
     void   UpdateScrollInfo();