Читать «Исчерпывающее руководство по написанию всплывающих подсказок» онлайн - страница 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.