Class们的分工合作安排,消息的传递。

来源:互联网 发布:classware软件下载 编辑:程序博客网 时间:2024/05/16 07:44

现在,有了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; // 滚轮偏移量
 };

原创粉丝点击