Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Tool tip на CView


Автор: Rapalex 17.8.2007, 12:04
У меня есть вдид документа (наследник от CView), наделён возможностями скролига, на нём рисуются различные объекты (НЕ прямоугольные).

Нужно выдать Tool tip при наведении мышки на него, а в тул типе было (например) его название.
Хотелось бы чтоб было также красиво ка у тулбаров.

Порылся в хелпе нашол:
тултипы для тулбаров (CToolBarCtrl) - не подходит
CToolTipCtrl - когда полоьзовался, там всё привязывается к контролам, прямоугольника и текст задаётся при создании, тоже не подойдёт
для окна (EnableToolTips, CancelToolTips, FilterToolTipMessage, and OnToolHitTest) - пытался запустить так и не получилось.

Подскажите что делать, в каком направлении рыть.

Автор: FREEDEV 17.8.2007, 13:27
попробуй 
CToolTipCtrl

Автор: Rapalex 17.8.2007, 14:29
CToolBarCtrl - оппечатался я, хотел CToolTipCtrl написать.

FREEDEV, некатит.

Автор: FREEDEV 17.8.2007, 14:46
так а что именно не катит?

ты создаешь тултип

Код

tooltip.Create(this);
tooltip.AddTool(GetDlgItem(IDC_CONTROL), LPSTR_TEXTCALLBACK);


прописываешь его в карту сообщений

Код

BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
... 
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify)
END_MESSAGE_MAP()


и функцию для обработки

Код

BOOL CMyDlg::OnToolTipNotify(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
{ 
    TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR; 
    UINT nID = pNMHDR->idFrom;

    if (nID == IDC_CONTROL) // Fill in the text buffer
    {
        _tcscpy(pTTT->szText, _T("Tooltip text\rExtended tooltip text"));
        return TRUE;
    }

    return FALSE;
}


Это с кодепроджекта, посмотри там есть примеры. Я дома поищу, где-то должны быть проекты с ТулТипом

Автор: Rapalex 17.8.2007, 15:03
Сенкс, вечером попробую.

Автор: Earnest 17.8.2007, 15:18
В принципе, способов 2:
Первый:
1) В конструкторе вью пишешь EnableToolTips();
2) Переопределяешь виртуальную функцию OnToolHitTest, в которой все и делаешь. Только надо помнить, что твои области - это не окно.
В этом случае работает общий тултип MFC-оболочки: каждый раз предыдущий тул уничтожается, а новый (если есть) - добавляется.

Второй способ (чуть сложнее, но и гибче):
Внутри вью создаешь свой собственный тултип и менеджишь его как описано в MSDN, а также
http://rsdn.ru/article/controls/tiptoe.xml
Этот способ лучше тем, что ты имеешь свой отдельный тултип, который можешь сделать многострочным, цветным, ... 

Автор: Rapalex 20.8.2007, 12:30
Earnest, так что у каж дого окна есть свой тулип, просто не отоброжается? (я про про первый способ)

Автор: Earnest 20.8.2007, 14:55
Как раз наоборот: есть один тултип на всю MFC-программму. И у него один или 0 тулов в каждый момент. Посмотреть, как все работает, можно в файле tooltip.cpp (в сорсах MFC). Функция называется CWnd::FilterTooltipMessage (как-то так).
Но я бы тебе рекомендовала второй способ: он более управляемый, только немного разобраться нужно.
А первый оставь для тултипов к кнопкам тулбаров и диалоговых панелей (т.е. когда тебе самому ничего делать не надо - только строки прописать).

Автор: Rapalex 20.8.2007, 15:18
Понял, этотже тултип над тулбарами выскакиает.
А второй способ это то что FREEDEV сказал, и подразумевает использование CToolTipCtrl?

Автор: Earnest 20.8.2007, 15:28
Да, конечно - я же тебе ссылку дала.

Автор: Rapalex 20.8.2007, 15:31
Понял, спасибо, уже начал делать...

Автор: Rapalex 20.8.2007, 17:19
Эх....
Earnest, что в твоём примере что в коде FREEDEV все ссылались на сообщение TTN_NEEDTEXT. В хелпе написано:
Цитата

If you specify the LPSTR_TEXTCALLBACK value in the lpszText member, the ToolTip control notifies the window specified in the hwnd member of the TOOLINFOstructure whenever the ToolTip control needs to display text for the tool. The ToolTip control sends the TTN_GETDISPINFO notification message to the window. The message includes the address of a NMTTDISPINFO structure, which contains the window handle as well as the application-defined identifier for the tool. The window examines the structure to determine the tool for which text is needed, and it fills the appropriate structure members with information that the ToolTip control needs in order to display the string.
 Попробывал я TTN_GETDISPINFO, так и не понял какое надо обробатывать чтоб правильно было.

Разница для меня: TTN_GETDISPINFO - нет возвращаемого значения.

Мина, в которую вступил - когда я поменял текст сообщения сообщение поменялось у всех кнопок тулбара, когда стал проверять поподание мышки в клиентскую часть окна, всё прошло.

С TTN_NEEDTEXT если мышка не в окне возварщал FALSE и все тулбары работали, в TTN_GETDISPINFO так нельзя.

Остался только один вопрос: Как выключить подсказку если мышка не над нарисованым объектом? (правильно)

Автор: FREEDEV 21.8.2007, 09:55
Цитата(Rapalex @  20.8.2007,  17:19 Найти цитируемый пост)
Остался только один вопрос: Как выключить подсказку если мышка не над нарисованым объектом? (правильно)


так убирай подсказку вообще, по движению мышки

Добавлено через 2 минуты и 33 секунды
или ты в документе не можешь определить где у тебя есть объекты, где нет ?

Автор: Earnest 21.8.2007, 10:05
TTN_NEEDTEXT == TTN_GETDISPINFO.
Возвращаемое значение есть всегда. Просто подключай обработчик через ON_NOTIFY_EX: 
Код

   ON_NOTIFY_EX (TTN_NEEDTEXT, 0, OnDataTipNeedText)

Соответственно, сигнатура у него должна быть другая. Вот пример, выдранный из кода:
Код

BOOL CVirtView::OnDataTipNeedText (UINT id, NMHDR* pNMHDR, LRESULT* pResult)
{
   CPoint ptPos; 
   ::GetCursorPos (&ptPos);

   CWnd* pWnd = WindowFromPoint (ptPos);
   if (!pWnd || pWnd->m_hWnd != m_hWnd)
      return FALSE;

   TOOLTIPTEXT* pInfo = (TOOLTIPTEXT*)pNMHDR;

   // Чтобы не ограничиваться длиной буфера pInfo->szText (80 символов!)
   // держим статическую строку
   static CString _strTip;

   ScreenToClient (&ptPos);
   m_lastDataHit = m_pTool->GetDataTipInfo (ptPos, _strTip);
   if (m_lastDataHit < 0)
      pInfo->lpszText = 0;
   else
      pInfo->lpszText = _strTip.GetBuffer();

   return TRUE;
}


m_lastDataHit = m_pTool->GetDataTipInfo (ptPos, _strTip);
Тут мы спрашиваем у некоего агента, как там с данными. m_lastDataHit - это int, мы его храним, чтобы на MouseMove правильно спрятать\показать тултип:
Код

void CVirtView::OnMouseMove (UINT nFlags, CPoint pt) 
{
   // поддержка тултипов
   if (::IsWindow (m_wndDataTip.m_hWnd))
   {
      CString str;
      int hit = m_pTool->GetDataTipInfo (pt, str);
      if (hit != m_lastDataHit)
      {
         // прячем 
         m_wndDataTip.Pop();        

         if (hit != -1)
         {
            // показываем
            m_wndDataTip.SendMessage (TTM_POPUP);
            m_lastDataHit = hit;
         }
      }
   }
}

Тут еще нужно позаботиться о том, чтобы для различных участков экрана (объектов) возвращались разные int-значения.
m_wndDataTip - это и есть CToolTipCtrl, который создаем на OnCreate и устанавливаем ему всякие параметры:
Код

   if (m_wndDataTip.Create (this, TTS_ALWAYSTIP) && m_wndDataTip.AddTool (this))
   {
      m_wndDataTip.SetMaxTipWidth (SHRT_MAX);
      m_wndDataTip.SetDelayTime (TTDT_AUTOPOP, SHRT_MAX);      // висеть до посинения
      m_wndDataTip.SetDelayTime (TTDT_INITIAL, 200);           // пауза от остановки курсора до появления тултипа (мс)
      m_wndDataTip.SetDelayTime (TTDT_RESHOW,  200);
   }


Ну, еще в PreTranslateMessage есть такой кусок:

Код

   // транслируем сообщение тултипу
   if (::IsWindow (m_wndDataTip.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_wndDataTip.RelayEvent (pMsg);
            break;
      }
   }

Вот и вся обработка.

Автор: Rapalex 21.8.2007, 10:44
Мда.
Код

#define TTN_NEEDTEXT            TTN_GETDISPINFO

Это вообще одно и тоже.

Добавлено через 3 минуты и 20 секунд
Вроде сделал. Сенкс.

Автор: Rapalex 27.3.2008, 13:10
Earnest, спасибо ещёраз, на неделе пришлось переделывать тултипы, и заметил такукую запалдяну.

Навожу мышку жду и тултип появляется, потом сразу гаснет, а потом опять появлется такое непонятное мерцание.
Все сделал почти так ты сказала, только тултип я сам не показываю (TTM_POPUP не посылаю).

Автор: Earnest 27.3.2008, 18:54
А ты посылай. 
Я уже тонкостей не помню, но тот код, который я приводила 100% рабочий и ничего не моргает. Там ничего лишнего нет.

Автор: Rapalex 27.3.2008, 21:26
Работает не спорю, а если посылаю то тултип раньше времени выскакивает.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)