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.
CWebButtonCtrl::OnToolHitTest вызывается функцией CWnd::FilterToolTipMessage, и я переопределил ее реализацию по умолчанию, чтобы заполнить передаваемую ей структуру TOOLINFO. Заполнение структуры происходит только в том случае, если для элемента разрешены подсказки. Подсказка (элемент ToolTip) будет показана на экране только при заполненных полях структуры TOOLINFO. Остальные проверки на NULL и размер структуры – избыточные проверки входных параметров на корректность. После заполнения структуры TOOLINFO функция устанавливает поле rect равным размеру клиентской части кнопки. Другими словами, вся кнопка задается как один инструмент. Полю lpszText присваивается значение LPSTR_CALLBACK, в результате чего элемент ToolTip посылает уведомление TTN_NEEDTEXT, чтобы получить текст подсказки. CWebButtonCtrl::OnToolNeedText обрабатывает это уведомление от элемента ToolTip, копируя строку из m_strToolTipText в поле szText переданной структуры TOOLTIPTEXT.