用Kinect来控制鼠标的移动、单击、双击和右击 (Windows sdk)

 定义一个结构
class MyPoint
{
public:
	float fx;
	float fy;
	USHORT depth;
}; 

然后将骨骼各节点信息保存起来:(其实这里只用到了左右手的节点信息)

for (i = 0; i < NUI_SKELETON_POSITION_COUNT; i++)
{
		 
	// Add new position to the history buffer
	m_History[i].push_front(point);
	// Keep size of history buffer
	if (m_History[i].size() > m_nThreshold)
		m_History[i].pop_back();
}
从保存的数据中取出信息,控制鼠标:

void CKinect::HandleMouseMoveAndClick( )
{
  
	if( m_History[NUI_SKELETON_POSITION_HAND_RIGHT].size( ) >= m_nThreshold )
	{
		// 新点;
		MyPoint newPoint;
		newPoint.fx = m_History[NUI_SKELETON_POSITION_HAND_RIGHT].front().fx;
		newPoint.fy = m_History[NUI_SKELETON_POSITION_HAND_RIGHT].front().fy;
		newPoint.depth = m_History[NUI_SKELETON_POSITION_HAND_RIGHT].front().depth;
 

		// 旧点;
		MyPoint oldPoint;   
		std::list< MyPoint >::iterator iter=  m_History[NUI_SKELETON_POSITION_HAND_RIGHT].begin( );
		iter++;
		oldPoint.fx = iter->fx;
		oldPoint.fy = iter->fy;
		oldPoint.depth = iter->depth;

		// 左手新点;
		MyPoint newPointLeft;
		newPointLeft.fx = m_History[NUI_SKELETON_POSITION_HAND_LEFT].front().fx;
		newPointLeft.fy = m_History[NUI_SKELETON_POSITION_HAND_LEFT].front().fy;
		newPointLeft.depth = m_History[NUI_SKELETON_POSITION_HAND_LEFT].front().depth;
  
		// 屏幕坐标系 转换因子;
		int screenWidth   =  rcWorkArea.Width(); // GetSystemMetrics(SM_CXSCREEN); 
		int screenHeight  =  rcWorkArea.Height();// GetSystemMetrics(SM_CYSCREEN); 
		 
		newPoint.fx = newPoint.fx * screenWidth ;
		newPoint.fy = newPoint.fy * screenHeight ;
		oldPoint.fx = oldPoint.fx * screenWidth ;
		oldPoint.fy = oldPoint.fy * screenHeight ;

 		// 求位差;
		float  xOffset = newPoint.fx - oldPoint.fx;
		float  yOffset = newPoint.fy - oldPoint.fy;


		// 计算位移结果;
		POINT currentPoint;
		POINT resultPoint;
		::GetCursorPos( ¤tPoint );// 获取当前鼠标位置

		if(xOffset < 30 || yOffset < 30)
		{
			resultPoint.x = static_cast<int>(currentPoint.x + xOffset*2.5+0.5);
			resultPoint.y = static_cast<int>(currentPoint.y + yOffset*2.2+0.5);
		}else if(xOffset < 80 || yOffset < 80)
		{
			resultPoint.x = static_cast<int>(currentPoint.x + xOffset*2.8 +0.5);
			resultPoint.y = static_cast<int>(currentPoint.y + yOffset*2.5 +0.5);
		}else  
		{
			resultPoint.x = static_cast<int>(currentPoint.x + xOffset*3.1+0.5);
			resultPoint.y = static_cast<int>(currentPoint.y + yOffset*3.1+0.5);
		}

		// 评价;
		if( resultPoint.x <= 0 ) 
			resultPoint.x = 0;
		if( resultPoint.x >= screenWidth )
			resultPoint.x = screenWidth;
		if( resultPoint.y <=0 )
			resultPoint.y = 0;
		if( resultPoint.y >= screenHeight )
			resultPoint.y = screenHeight;

		SetCursorPos( resultPoint.x , resultPoint.y );// 设置鼠标位置

		// 处理鼠标点击; 
		// 将特定的控件存放到容器中,使得只在指定的控件上实施点击:MousePointInCtrRect(m_hWnd,vecItemIDs,currentPoint)
		vector<int> vecItemIDs;
		vecItemIDs.push_back(IDC_HANDCTR);
		vecItemIDs.push_back(IDC_PPTCTR); 
		vecItemIDs.push_back(IDC_BUTTON1);
		vecItemIDs.push_back(IDC_BUTTON3);
		vecItemIDs.push_back(IDC_LIST_MER);
		
		// 不存在位移比较大的点; 
		if((abs(newPoint.fx-oldPoint.fx) < 5
			|| abs(newPoint.fy-oldPoint.fy) < 5)  
			&& MousePointInCtrRect(m_hWnd,vecItemIDs,currentPoint) )
		{
			if(m_flagRecordBegin == 1)
			{
				m_start = clock();// 记录单击起始时间;	
				m_flagRecordBegin = 0; 
			}
			if(m_flagRecordBeginDoubleClick == 1)
			{
				m_startDoubleClick = clock(); // 记录双击起始时间;	
				m_flagRecordBeginDoubleClick = 0; 
			}
			clock_t now = clock(); 
			if(now - m_start > 700 && now - m_start <= 1400)  
			{  
				 
				if(m_flagRightClick == false)//只记一次;
				{
					oldPointRight =  newPoint;
					oldPointLeft  =  newPointLeft;
					m_flagRightClick = true;
				}
			}  

			// 右手在指定控件的时间达到一定时间长度且左手向前移动,右击
			if(now - m_start > 1000 && now - m_start <= 3500 &&  (oldPointLeft.depth - newPointLeft.depth) >  2000 ) 
			{  
				m_flagRecordBegin = 1;
				m_flagRecordBeginDoubleClick = 1;
				this->RightClick();
				m_flagRightClick = false;  
			}

			// 右手在指定控件的时间达到一定时间长度,左击
			if(now - m_start > 3500  )
			{   
					this->LeftClick() ;   
					m_flagRecordBegin = 1;
					m_flagRightClick = false; 
			}

			// 右手在指定控件的时间达到一定时间长度,双击
			if(now - m_startDoubleClick > 6000  )
			{ 
				this->LeftClick() ; 
				this->LeftClick() ;  
				m_flagRecordBegin = 1;
				m_flagRecordBeginDoubleClick = 1;
				
			}

		}else{// 操作位移较大的点,重新计时;
			m_flagRecordBegin = 1; 
			m_flagRecordBeginDoubleClick = 1;
		} 
	}
}

判断鼠标当前是否在指定控件上函数(MFC)
bool CKinect::MousePointInCtrRect(HWND hwnd,vector<int> nItemNo,POINT point)
{ 
  
	for (size_t i=0; i < nItemNo.size(); i++)
	{
		CRect   rect; 
		GetWindowRect(GetDlgItem(m_hWnd,nItemNo[i]),&rect); 
		if(point.x> rect.left&&point.x <rect.right&&point.y <rect.bottom&&point.y> rect.top)
		{  
			return true;
		} 
	}
	return false;
}
左击、右击:

void CKinect::LeftClick () {  
	INPUT    Input = {0};
	// left down 
	Input.type        = INPUT_MOUSE;
	Input.mi.dwFlags  = MOUSEEVENTF_LEFTDOWN;
	::SendInput(1,&Input,sizeof(INPUT));

	// left up
	::ZeroMemory(&Input,sizeof(INPUT));
	Input.type        = INPUT_MOUSE;
	Input.mi.dwFlags  = MOUSEEVENTF_LEFTUP;
	::SendInput(1,&Input,sizeof(INPUT)); 
}

void CKinect::RightClick () {  
	INPUT    Input = {0};
	// left down 
	Input.type        = INPUT_MOUSE;
	Input.mi.dwFlags  = MOUSEEVENTF_RIGHTDOWN;
	::SendInput(1,&Input,sizeof(INPUT));

	// left up
	::ZeroMemory(&Input,sizeof(INPUT));
	Input.type        = INPUT_MOUSE;
	Input.mi.dwFlags  = MOUSEEVENTF_RIGHTUP;
	::SendInput(1,&Input,sizeof(INPUT)); 
}

鼠标移动如果不够平滑,可以考虑线性插值? 




  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值