您的位置:首页 > 其它

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

2011-12-01 22:35 471 查看
定义一个结构
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(currentPoint.x + xOffset*2.5+0.5);

resultPoint.y = static_cast(currentPoint.y + yOffset*2.2+0.5);

}else if(xOffset < 80 || yOffset < 80)

{

resultPoint.x = static_cast(currentPoint.x + xOffset*2.8 +0.5);

resultPoint.y = static_cast(currentPoint.y + yOffset*2.5 +0.5);

}else 

{

resultPoint.x = static_cast(currentPoint.x + xOffset*3.1+0.5);

resultPoint.y = static_cast(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 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 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.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)); 

}

鼠标移动如果不够平滑,可以考虑线性插值? 要想实现使用kinect来控制ppt,可以在定义好手势后发送PageUp,PageDown,F5,Shift+F5,以及ESC等键盘信息。

这样就可以了,代码就不贴了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息