现在,有了CCursor类,有了CDesktop类,要开始考虑它们的合作问题了。
首先我的基本想法是从CCursor类得到鼠标的事件信息,把按钮状态、指针位置的信息传递给CDesktop,CDesktop根据相应的消息,执行指定的命令。
CDesktop类保存的桌面数据:
当前焦点窗口:一个CWin*指针,处于最上方的窗口。
当前焦点控件:一个CWin*指针,当前激活窗口用有焦点的控件。
当前鼠标指针状态:一个bool类型变量,表示正常,拖拽(焦点窗口跟随鼠标指针移动)两种情况。
拖拽源(窗口/控件):一个CWin*指针,在松开鼠标的时候,如果放下的目标区域在一个窗口内,则传递DragDrop消息给目标窗口,参数为拖拽源的指针。拖拽常常应用于装备、物品等等拖放行为之上。
拖拽X偏移,拖拽Y偏移:int变量,鼠标指针拖起窗口时相对窗口left, top的偏移量。用于更新窗口位置。
双击判断的问题:
几经修改,处理鼠标缓冲区的函数已经完善了。它能够记录鼠标按钮变化的次数,以及Z轴的偏移,还有双击次数,单击次数等等。双击由于最长用的是左键双击,所以只关注了左键双击的行为。
处理函数如下:
// 处理鼠标缓冲区的数据
void CCursor::GetMouseData(MOUSE_EVENT_STRUCT *e)
{
if ( ! e ) // 无效参数
return ;
// 清空输出
memset( e, 0, sizeof( MOUSE_EVENT_STRUCT ) );
DIDEVICEOBJECTDATA od;
HRESULT hr;
DWORD dwCount = 1; // 缓冲区数据条数
static DWORD dwLastDown = 0; // 上次按下的时间
static DWORD dwLastDblClick = 0; // 上次双击的时间
DWORD dwNowDown = 0; // 这次按下的时间
BOOL bDblClicked = false; // 返回是否双击
while ( TRUE )
{
dwCount = 1;
// 获取鼠标缓冲区数据
hr = m_lpDIMouse->GetDeviceData( sizeof( DIDEVICEOBJECTDATA ), &od , &dwCount , 0 );
if ( hr == DIERR_INPUTLOST )
{
// 鼠标设备丢失, 恢复并返回
m_lpDIMouse->Acquire();
return ;
}
// 数据获取失败, 或者缓冲区已经获取完毕
if ( (FAILED ( hr )) || (dwCount == 0) )
break;
// 处理缓冲内容
switch ( od.dwOfs )
{
case DIMOFS_X:
// X 偏移;
case DIMOFS_Y:
// Y 偏移
break;
case DIMOFS_Z:
// Z 偏移 ( 鼠标滚轮 )
e->nMouseWheel += (short)od.dwData;
break;
case DIMOFS_BUTTON0:
if ( od.dwData & 0x80)
{
// 左键按下
if ( dwLastDown == 0 )
dwLastDown = od.dwTimeStamp;
else
dwNowDown = od.dwTimeStamp;
e->bLButtonDown ++;
}else{
// 左键松开
e->bRButtonUp ++;
}
break;
case DIMOFS_BUTTON1:
if ( od.dwData & 0x80)
{
// 右键按下
e->bRButtonDown ++;
}else{
// 右键松开
e->bRButtonUp ++;
}
break;
}
// 检查是否有双击事件, 时间在 系统设定有效双击区间 的两次点击视为有效双击.
if ( dwNowDown )
if ( (dwNowDown - dwLastDown) < m_dblClickTime )
{
e->nDblClicked ++;
dwLastDown = 0;
} else if ( dwNowDown - dwLastDown > m_dblClickTime ){
// 超时, 重置时间
dwLastDown = dwNowDown;
}
} // end while
return ;
}
其中参数 e 是一个 MOUSE_EVENT_STRUCT,这个参数将会返回这次缓冲区数据处理的结果,用于跟指针坐标一齐传递CDesktop处理鼠标事件。这个变量结构如下:
static struct MOUSE_EVENT_STRUCT{
BOOL DblClicked; // 有效双击(次数)
BOOL LButtonUp; // 左键曾经松开
BOOL RButtonUp; // 右键曾经松开
BOOL LButtonDown; // 左键曾经按下 (单击次数, 单击.)
BOOL RButtonDown; // 右键曾经按下
int nMouseWheel; // 滚轮偏移量
};