Отслеживание всплывающей подсказки в CScrollView?

В стандартном проекте C ++ / MFC MDI doc / view я хочу реализовать всплывающую подсказку отслеживания в представлении (окна представления с вкладками, которые обычно занимают большую часть окна основного фрейма). Итак, в классе MyAppViewУ меня есть член CToolTipCtrl tooltip, функция MyAppView::OnInitialUpdate() содержит инициализацию

BOOL ok0 = tooltip.Create(this, TTS_ALWAYSTIP);
CRect clientRect; GetClientRect(&clientRect);
BOOL ok2 = tooltip.AddTool(this, LPSTR_TEXTCALLBACK, &clientRect, 1234/*tool ID*/);
tooltip.Activate(TRUE);

сделать всю клиентскую область представления «инструментом». Карта сообщений содержит запись

ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnNeedToolTipText)

и функция OnNeedToolTipText определяется как

BOOL MyAppView::OnNeedToolTipText(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{
UNREFERENCED_PARAMETER(id);

NMTTDISPINFO *pTTT = (NMTTDISPINFO *)pNMHDR;
UINT_PTR nID = pNMHDR->idFrom;
BOOL bRet = FALSE;
if(nID == 1234)
{
// Come here when text is needed for tracking tooltip
}
if(pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
_stprintf_s(pTTT->szText, sizeof(pTTT->szText) / sizeof(TCHAR),
_T("Control ID = %d"), nID);
pTTT->hinst = AfxGetResourceHandle();
bRet = TRUE;
}
}

*pResult = 0;

return bRet;
}

То, что происходит, — то, что только размещение мыши на пунктах меню (Файл, Редактировать, Вид, Окно, Справка) приводит к вводу кода OnNeedToolTipTextс идентификатором 0-5. Перемещение мыши в клиентскую область (вид) ничего не делает.

Как заставить всплывающую подсказку появляться только в клиентской области представления?

Visual Studio 2017; C ++; 64-битная Windows 7

0

Решение

Для решения проблемы необходимо сделать следующее:

BOOL CMyAppView::PreTranslateMessage(MSG* pMsg)
{
switch (pMsg->message)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_MOUSEMOVE:
if (m_pToolTip->GetSafeHwnd () != NULL)
{
m_pToolTip->RelayEvent(pMsg);
}
break;
}

return CScrollView::PreTranslateMessage(pMsg);
}
0

Другие решения

Если вам нужна подсказка для отслеживания в представлении, выполните следующие действия:

Создайте подсказку и добавьте инструмент.

void CToolTipDemoView::OnInitialUpdate()
{
// ...

m_toolTip.Create(this, TTS_ALWAYSTIP | TTS_NOANIMATE);
m_toolTip.AddTool(this, _T("Doesn't matter"));
}

Обрабатывать сообщение WM_MOUSEMOVE. Сначала вызовите _TrackMouseEvent, чтобы в дальнейшем получить WM_MOUSELEAVE и активировать всплывающую подсказку. Во-вторых, обновите текст подсказки и покажите его в координатах указателя мыши.

void CToolTipDemoView::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bTrackingMouseLeave)
{
TRACKMOUSEEVENT tme = { 0 };
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = m_hWnd;
::_TrackMouseEvent(&tme);

m_toolTip.Activate(TRUE);
m_bTrackingMouseLeave = TRUE;
}

if (m_pointLastMousePos != point)
{
CString strText;
strText.Format(_T("x = %d y = %d"), point.x, point.y);
m_toolTip.UpdateTipText(strText, this);
m_toolTip.Popup();
m_pointLastMousePos = point;
}

CScrollView::OnMouseMove(nFlags, point);
}

Обработайте WM_MOUSELEAVE и деактивируйте подсказку.

void CCToolTipDemoView::OnMouseLeave()
{
m_bTrackingMouseLeave = FALSE;

// mouse pointer leaves the window so deactivate the tooltip
m_toolTip.Activate(FALSE);

CScrollView::OnMouseLeave();
}

Заметки:

  • больше нет необходимости обрабатывать TTN_NEEDTEXT.
  • кроме того, больше нет необходимости переопределять PreTranslateMessage
0

Поэтому я вернулся, чтобы посмотреть, чего мне не хватает. Я написал это более 10 лет назад. Я также переопределил член CWnd

virtual INT_PTR OnToolHitTest( CPoint point, TOOLINFO* pTI ) const;

С:

INT_PTR HERichView::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const
{
pTI->hwnd = m_hWnd;
pTI->uId = point.x + ( point.y << 16 );
CRect rect;
GetClientRect( rect );
pTI->rect= rect;
pTI->lpszText= LPSTR_TEXTCALLBACK;
return pTI->uId;
}

И я проверил, без этого не получится. Так что ваши:

ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTip )

Должен позвонить, если вы добавите выше. И только EnableToolTips( ); Должно быть необходимо.

0

Мне не удалось заставить всплывающую подсказку работать в MFC. Самое близкое, что я пришел, это

В карте сообщений: ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnNeedToolTipText)

В OnInitialUpdate: BOOL ok1 = EnableTrackingToolTips(TRUE);

В переопределении виртуальной функции OnToolHitTest:

    pTI->hwnd = m_hWnd;
pTI->uId = (UINT_PTR)m_hWnd;
pTI->uFlags = TTF_IDISHWND | TTF_ALWAYSTIP | TTF_TRACK | TTF_NOTBUTTON | TTF_ABSOLUTE | TTF_SUBCLASS;
pTI->lpszText = LPSTR_TEXTCALLBACK;
return pTI->uId;

В OnNeedToolTipText:

NMTTDISPINFO *pTTT = (NMTTDISPINFO *)pNMHDR;
UINT_PTR nID = pNMHDR->idFrom;
BOOL bRet = FALSE;
if(pTTT->uFlags & TTF_IDISHWND)
{
// idFrom is actually the HWND of the tool
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
CURSORINFO ci; ci.cbSize = sizeof(CURSORINFO); // get something interesting to display
GetCursorInfo(&ci);
_stprintf_s(pTTT->szText, sizeof(pTTT->szText) / sizeof(TCHAR),
_T("Control ID = %lld at (%d, %d)"), nID, ci.ptScreenPos.x, ci.ptScreenPos.y);
pTTT->hinst = AfxGetResourceHandle();
bRet = TRUE;
}
}
*pResult = 0;
return bRet;

Это производит следующее своеобразное поведение. Когда я запускаю приложение и перемещаю курсор мыши в клиентскую область CScrollView, рядом с курсором появляется всплывающая подсказка.

Если я аккуратно (плавно) перемещаю мышь, подсказка отслеживается правильно. Однако через некоторое время он исчезает, и никакие дальнейшие движения мыши, в том числе выход из окна CScrollView и возвращение, не вызывают его повторное появление.

Я думаю, что происходит, когда курсор мыши перемещается над окном подсказки, подсказка отключается навсегда. Это исчезновение, похоже, не связано со временем (например, из-за автоматического всплытия); если мышь оставить нетронутой, всплывающая подсказка останется на неопределенный срок.

0
По вопросам рекламы [email protected]