Читать «Исчерпывающее руководство по написанию всплывающих подсказок» онлайн - страница 10

Роджер Джек

 BOOL bHandledNotify = FALSE;

 CPoint CursorPos;

 VERIFY(::GetCursorPos(&CursorPos));

 ScreenToClient(&CursorPos);

 CRect ClientRect;

 GetClientRect(ClientRect);

 // Удостовериться, что курсор попадает в клиентскую область окна,

 // потому что библиотека тоже хочет получать эти сообщения для

 // показа подсказок на панели инструментов.

 if (ClientRect.PtInRect(CursorPos)) {

  TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;

  m_pCircleHit = HitTest(CursorPos);

  if (m_pCircleHit) {

   // Adjust the text by filling in TOOLTIPTEXT

   CString strTip;

   const CPoint& Center = m_pCircleHit->GetCenter();

   COLORREF Color = m_pCircleHit->GetColor();

   strTip.Format("Center: (%d, %d)\nRadius: %d\nColor: (%d, %d, %d)", Center.x, Center.y, m_pCircleHit->GetRadius(), (int)GetRValue(Color), (int)GetGValue(Color), (int)GetBValue(Color));

   ASSERT(strTip.GetLength() < sizeof(pTTT->szText));

   ::strcpy(pTTT->szText, strTip);

   // Set the text color to same color as circle

   m_ToolTip.SendMessage(TTM_SETTIPTEXTCOLOR, Color, L);

  } else {

   pTTT->szText[0] = 0;

  }

  bHandledNotify = TRUE;

 }

 return bHandledNotify;

}

BOOL CDTDemoView::PreTranslateMessage(MSG* pMsg) {

 if (::IsWindow(m_ToolTip.m_hWnd) && pMsg->hwnd == m_hWnd) {

  switch(pMsg->message) {

  case WM_LBUTTONDOWN:

  case WM_MOUSEMOVE:

  case WM_LBUTTONUP:

  case WM_RBUTTONDOWN:

  case WM_MBUTTONDOWN:

  case WM_RBUTTONUP:

  case WM_MBUTTONUP:

   m_ToolTip.RelayEvent(pMsg);

   break;

  }

 }

 return CView::PreTranslateMessage(pMsg);

}

void CDTDemoView::OnMouseMove(UINT nFlags, CPoint point) {

 if (::IsWindow(m_ToolTip.m_hWnd)) {

  const CCircle* pCircleHit = HitTest(point);

  if (!pCircleHit || pCircleHit != m_pCircleHit) {

   // Activate() скрывает подсказку.

   m_ToolTip.Activate(FALSE);

  }

  if (pCircleHit) {

   m_ToolTip.Activate(TRUE);

   m_pCircleHit = pCircleHit;

  }

 }

 CView::OnMouseMove(nFlags, point);

}

CDTDemoView::OnInitialUpdate создает DataTip и подготавливает его к использованию. Я вызываю m_ToolTip.Create и передаю ей TTS_ALWAYSTIP, чтобы DataTip показывался независимо от того, активно приложение или нет. Затем я вызываю m_ToolTip.AddTool и передаю ей CDTDemoView, как окно, содержащее инструмент. Из-за того, что последние параметры в CToolTipCtrl::AddTool имеют значения по умолчанию (LPSTR_TEXTCALLBACK как текст подсказки, NULL для параметра lpRectTool и 0 для nIDTool), все окно будет считаться инструментом и нотификационное сообщение TTN_NEEDTEXT будет послано CDTDemoView. Эта сообщение позволяет мне установить текст подсказки в функции CDTDemoView::OnToolTipNeedText.

Я посылаю несколько сообщений элементу DataTip, чтобы подготовить его к использованию. TTM_SETMAXTIPWIDTH посылается с заведомо большим значением (SHRT_MAX) в параметре lParam для установки максимальной ширины подсказки.[2] Это заставляет элемент ToolTip распознавать символы новой строки в строке подсказки (новая возможность IE 4.0 Common Controls DLL). Затем я три раза посылаю сообщение TTM_SETDELAYTIME.[3] В первый раз параметр wParam имеет значение TTDT_AUTOPOP, для установки времени, которое должно пройти до того, как ToolTip исчезнет. Время инициализируется в параметре lParam заведомо большим значением (SHRT_MAX), чтобы отключить автоисчезание подсказок.[4] Теперь я могу контролировать их время жизни. Во второй раз в wParam передается TTDT_INITIAL, что задает интервал между моментом остановки курсора мыши и первым появлением подсказки. Этот интервал устанавливается в 200 миллисекунд, поэтому подсказка появляется довольно быстро. И, наконец, TTDT_RESHOW устанавливает временной интервал между появлением следующей подсказки при перемещении курсора в другой круг. Этот интервал также установлен в 200 миллисекунд. Почему я не использовал CToolTipCtrl::SetDelayTime для установки интервалов? К сожалению, CToolTipCtrl::SetDelayTime позволяет задать только интервал для TTDT_AUTOMATIC.