Исчерпывающее руководство по написанию всплывающих подсказок - [3]

Шрифт
Интервал

Рис.4. HTML-код для подсказки

>

>

>
Image ToolTip

>

Элемент ActiveX представляет собой кнопку с подсказкой. Для чего мне возиться с созданием кнопки, когда можно добавить на Web-страницу трехмерную картинку, которая будет выглядеть как кнопка? На это есть две причины. Во-первых, кнопка выглядит реалистичнее – она нажимается и отжимается по щелчку пользователя, как и положено настоящей кнопке. Во-вторых, я хотел показать добавление подсказок к элементам ActiveX, а кнопка – это простейший элемент, который я мог использовать в демонстрационных целях.

Для генерации кода я использовал AppWizard. Я установил флажок "Activate when visible" и отключил все остальные флажки. В опции "Which window class, if any, should this control subclass?" я выбрал BUTTON. AppWizard генерирует массу дополнительного кода, не относящегося к данной статье. В основном, я остановлюсь на коде, добавленном мной в класс CWebButtonCtrl (см. рис.5). Давайте для начала взглянем на пару переменных класса. CWebButtonCtrl::m_bToolTipEnabled устанавливается в TRUE, если подсказки разрешены. В CWebButtonCtrl::m_strToolTipText хранится текст подсказки. Я добавил обе переменные через ClassWizard и они представляют OLE-свойства, автоматические обновляемые библиотекой MFC при их изменении.

Рис.5. CWebButtonCtrl

>// WebButtonCtl.cpp : Implementation of the CWebButtonCtrl OLE control class.


>/////////////////////////////////////////////////////////////////////////////

>// CWebButtonCtrl::RelayToolTipEvent – Pass mouse messages to ToolTip

>void CWebButtonCtrl::RelayToolTipEvent(const MSG* pMsg) {

> MSG MsgCopy;

> ::memcpy(&MsgCopy, pMsg, sizeof(MSG));

> FilterToolTipMessage(&MsgCopy);

>}


>int CWebButtonCtrl::OnToolHitTest(CPoint point, TOOLINFO* pTI) const {

> if (m_bToolTipEnabled && pTI != NULL && pTI->cbSize >= sizeof(TOOLINFO)) {

>  // setup the TOOLINFO structure

>  pTI->hwnd = m_hWnd;

>  pTI->uId = 0;

>  pTI->uFlags = 0;

>  GetClientRect(&(pTI->rect));

>  pTI->lpszText = LPSTR_TEXTCALLBACK;

> }

> return (m_bToolTipEnabled ? 1 : –1);

>}


>/////////////////////////////////////////////////////////////////////////////

>// CWebButtonCtrl message handlers

>int CWebButtonCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) {

> if (COleControl::OnCreate(lpCreateStruct) == –1) {

>  return –1;

> }

> if (m_Bitmap.LoadBitmap(IDB_WEBBUTTON)) {

>   SendMessage(BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)m_Bitmap.GetSafeHandle());

> } else {

>  TRACE("Unable to load bitmap for button.");

> }

> EnableToolTips(TRUE);

> return 0;

>}


>void CWebButtonCtrl::OnMouseMove(UINT nFlags, CPoint point) {

> RelayToolTipEvent(GetCurrentMessage());

> COleControl::OnMouseMove(nFlags, point);

>}


>void CWebButtonCtrl::OnLButtonDown(UINT nFlags, CPoint point) {

> RelayToolTipEvent(GetCurrentMessage());

> COleControl::OnLButtonDown(nFlags, point);

>}


>void CWebButtonCtrl::OnLButtonUp(UINT nFlags, CPoint point) {

> RelayToolTipEvent(GetCurrentMessage());

> COleControl::OnLButtonUp(nFlags, point);

>}


>BOOL CWebButtonCtrl::OnToolNeedText(UINT id, NMHDR * pNMHDR, LRESULT * pResult) {

>TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;

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

> return TRUE;

>}


>/////////////////////////////////////////////////////////////////////////////

>// Property changed handlers

>void CWebButtonCtrl::OnToolTipEnabledChanged() {

> SetModifiedFlag();

>}


>void CWebButtonCtrl::OnToolTipTextChanged() {

> SetModifiedFlag();

>}

CWebButtonCtrl::PreCreateWindow манипулирует передаваемой ему структурой CREATESTRUCT. Я задал для кнопки стиль пользовательской отрисовки (owner-draw) – BS_OWNERDRAW – для того, чтобы не рисовалась рамка фокуса (focus rect) при активизации кнопки. В противном случае, рамка была бы все время видна. Как побочный эффект задания такого стиля приходится переопределять функцию CWebButtonCtrl::OnOcmDrawItem для рисования кнопки. CWebButtonCtrl::OnCreate загружает и устанавливает картинку для кнопки посылкой сообщения BM_SETIMAGE. Она также вызывает CWebButton::EnableToolTips, чтобы задействовать поддержку подсказок классом CWnd.

Функции CWebButtonCtrl::OnMouseMove, CWebButtonCtrl::OnLButtonDown, и CWebButtonCtrl::OnLButtonUp делают одно и то же – они все вызывают CWnd::RelayToolTipEvent. Метод CWebButtonCtrl::RelayToolTipEvent делает неконстантную копию переданного ему сообщения и вызывает CWnd::FilterToolTipMessage. Копия сообщения делается из-за того, что CWnd::FilterToolTipMessage требует неконстантного указателя на сообщение. Я мог бы, конечно, привести указатель к неконстантному, но это небезопасно, потому что в этом случае CWnd::FilterToolTipMessage могла бы изменить исходное сообщение. Обычно CWnd автоматически вызывает CWnd::FilterToolTipMessage в функции CWnd::PreTranslateMessage. Однако, в элементе ActiveX сообщения мыши никогда не попадают в CWnd::PreTranslateMessage, она вызывается только как результат клавиатурного ввода (CWnd::PreTranslateMessage в основном используется для работы с клавиатурными акселераторами). В обычном MFC-приложении CWnd::PreTranslateMessage вызывается в результате работы функции CWinThread::PumpMessage.


Рекомендуем почитать
Параллельное программирование на С++ в действии. Практика разработки многопоточных программ

В наши дни компьютеры с несколькими многоядерными процессорами стали нормой. Стандарт С++11 языка С++ предоставляет развитую поддержку многопоточности в приложениях. Поэтому, чтобы сохранять конкурентоспособность, вы должны овладеть принципами и приемами их разработки, а также новыми средствами языка, относящимися к параллелизму.Книга «Параллельное программирование на С++ в действии» не предполагает предварительных знаний в этой области. Вдумчиво читая ее, вы научитесь писать надежные и элегантные многопоточные программы на С++11.


Дефрагментация мозга. Софтостроение изнутри

Эта книга для тех, кто давно связан с разработкой программного обеспечения. Или для тех, кто еще думает выбрать программирование своей профессией. Или для тех, кто просто привык думать и размышлять о происходящем в мире информационных технологий.Не секрет, что основная масса софтостроения сосредоточена в секторе так называемой корпоративной разработки: от комплексных информационных систем предприятия до отдельных приложений. Поэтому немалая часть сюжетов касается именно Enterprise Programming.Из текста вы вряд ли узнаете, как правильно склеивать многоэтажные постройки из готовых компонентов в гетерогенной среде, проектировать интерфейсы, синхронизировать процессы или писать эффективные запросы к базам данных.


Справочник по JavaScript

Вниманию читателей предлагается справочник по JavaScript.Справочник предназначается для людей, уже освоивших азы программирования в JavaScript.Справочник создан на основе информации, предоставленной на сайте «Справочник Web-языков» www.spravkaweb.ru.Дата выхода данной версии справочника: 12:33, 21 марта 2007.


Справочник по PHP

Вниманию читателей предлагается справочник по PHP.Справочник предназначается для людей, уже освоивших азы программирования на языке PHP.Справочник создан на основе информации, предоставленной на сайте «Справочник Web-языков» www.spravkaweb.ru.


Fiction Book Designer Краткое руководство

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Программирование на Visual C++. Архив рассылки

РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.