Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите разобраться с тултипами, С CToolTipCtrl 
V
    Опции темы
Rapalex
Дата 9.2.2009, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 732
Регистрация: 20.1.2006
Где: Украина -> Ник олаев

Репутация: 6
Всего: 8



Задача не нова. Есть у меня вид на нём нарисованы НЕ прямоугольные геометрические фигуры, типа пазла набросаны.
При наведении мышкой на них нужно подсветить например название той или иной фигуры, разумеется при поподании а фон они должны сразу пропасть. Конечно по координате мыши в окне могу быстро определить фигуру.

Если честно воспользоваться методом через EnableToolTips() и OnToolHitTest() не получилось, что-то там не чисто. Но мне он не очень та и подходит, там один тултип на всё МФЦ приложение и он прямоугольный, а мне нужно отобразить его с типом "балун".
Поэтому хотел воспользоваться CToolTipCtrl. Про LPSTR_TEXTCALLBACK знаю и обрабатывал TTN_NEEDTEXT, но из того обработчика не смогу сказать что тултипу не нужно появляться.

Если что-то не внятно обьянил, то это от того что сам не знаю)))
Люди подскажите как мне моё довести до ума, или расскажите как это правильно делается.
Спаибо.


--------------------
In vitium ducit culpae fuga.
Желание избежать ошибки вовлекает в другую.
(Horatius)
PM ICQ   Вверх
Earnest
Дата 9.2.2009, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Очень хорошо тебя понимаю, т.к. всегда сама с этим длом путаюсь. Слава богу, у меня есть работающие примеры (хоть сама писала-разбиралась, но уже не помню), с которых можно драть.
Итак, выборка из работающего кода: 
1) заводим в окне-виде переменную CToolTipCtrl m_wndDataTip
2) В обработчик OnCreate вида добавляем следующий код:
Код

   if (m_wndDataTip.Create (this, TTS_ALWAYSTIP | TTS_BALLOON) && 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);
   }

2) В 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;
      }
   }

В принципе, можно обойтись без RelayEvent, если использовать флаг SUBCLASS, и я где-то в другом месте (для всяких In-Place tooltips так делала, но этот код написан именно так, поэтому умничать не буду. Захочешь - сам экспериментируй.

4) В обработчик OnMouseMove вида добавляем следующий код:
Код

   // поддержка тултипов
   if (::IsWindow (m_wndDataTip.m_hWnd))
   {
      CString str;
      int hit = GetDataTipInfo  (pt,  str); // это функция, определяющая строку и хит по точке
// важно, чтобы хиты были разумными, неповторяющимися на экране и неотрицательными; 
// хороший выбор - неотрицательный ID объекта; 
// а, скажем, для вывода RGB точек растра я использую хэш-фукцию, замешивающую x и y точки. 
      if (hit != m_lastDataHit)  // m_lastDataHit хранит последний хит и инициализирован -1
      {
         // прячем 
         m_wndDataTip.Pop();        

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

5) Добавляем обработчик для обработки CALLBACK-текста
Код

ON_NOTIFY_EX (TTN_NEEDTEXT, 0, OnDataTipNeedText)

// формируем текст для тултипа
BOOL CMyView::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 = GetDataTipInfo (ptPos, _strTip);
   if (m_lastDataHit == -1)
      pInfo->lpszText = 0;
   else
      pInfo->lpszText = _strTip.GetBuffer();

   return TRUE;
}

Не помню уже, зачем здесь некоторый дубляж, но вроде иначе (без последнего обработчика) происходит путаница с MFC-тултипом, а без MouseMove - то ли не гаснет вовремя, то ли еще что-то. Возможно, если убрать CALLBACK из определения тула (т.е. не пользоваться стандартной AddTool), то можно обойтись без обработки TTN_NEEDTEXT. 
Но этот вариант, несмотря на некоторую избыточность, точно работает.


--------------------
...
PM   Вверх
Rapalex
Дата 10.2.2009, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 732
Регистрация: 20.1.2006
Где: Украина -> Ник олаев

Репутация: 6
Всего: 8



++1 Помогло)))


Только я не показывал и прятал тултип а вызывал Activate().

Замечание: строки
Код

            m_wndDataTip.SendMessage (TTM_POPUP);
            m_lastDataHit = hit;
 как минимум местами поменять, а лучше так сделать:
Код

    if (hit != m_lastDataHit)  // m_lastDataHit хранит последний хит и инициализирован -1
      {
         // прячем 
         m_wndDataTip.Pop();        
         m_lastDataHit = hit;
         if (hit != -1)
         {
            // показываем
            m_wndDataTip.SendMessage (TTM_POPUP);
         }
      }


Остался один баг, когда мышка выходит за приделы вида, возвращается и ждёт тултипа, то ттултип как бы дважды появляется, первый раз появился сразу пропал а потом появляется и висит как наужно.

И что за SUBCLASS и In-Place tooltips? По подробней рассказать можешь?


--------------------
In vitium ducit culpae fuga.
Желание избежать ошибки вовлекает в другую.
(Horatius)
PM ICQ   Вверх
Earnest
Дата 10.2.2009, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 87
Всего: 183



Цитата(Rapalex @  10.2.2009,  14:19 Найти цитируемый пост)
Остался один баг, когда мышка выходит за приделы вида, возвращается и ждёт тултипа, то тултип как бы дважды появляется, первый раз появился сразу пропал а потом появляется и висит как наужно.

Хм, не замечала. Впрочем у нас там много чего наверчено, на мышку-то, может нивелируется... Другое твое замечание - ну, может быть... Этот код довольно давно живет и вроде особых проблем не вызывает, а желания его вылизывать нет (как в том анекдоте, про закат солнца на западе  smile) 

Цитата(Rapalex @  10.2.2009,  14:19 Найти цитируемый пост)
И что за SUBCLASS и In-Place tooltips?

TTF_SUBCLASS это флаг, который можно присобачить TOOLINFO при добавлении тула. Тогда RelayEvent становиться не нужным, тултип контрол присабклассится к своему owner'у и сам следит за мышиными событиями.
In-Place ToolTips - это тултипы, которые показываются обычно вместо слишком длинных (обрезанных) строк, скажем, в три или лист-контролах при наведении мыши на не влезшую строку. Например, можно написать свой ComboBox (или Edit), где будет всплывать тултип на месте текстового окошка. Там вся фишка в том, чтобы визуально совместить текст тултипа с исходной строкой, чтобы это выглядело как разворачивание строки...



--------------------
...
PM   Вверх
Rapalex
Дата 10.2.2009, 14:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 732
Регистрация: 20.1.2006
Где: Украина -> Ник олаев

Репутация: 6
Всего: 8



Понял, спасибо.


--------------------
In vitium ducit culpae fuga.
Желание избежать ошибки вовлекает в другую.
(Horatius)
PM ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.0469 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.