为自定义控件添加ToolTip时,一般做法是在PreTranslateMessage中添加如下代码:
if (NULL != m_pToolTipCtrl)
m_pToolTipCtrl->RelayEvent(pMsg);
希望CToolTipCtrl能够捕获鼠标移动等消息,但是结果PreTranslateMessage方法在ActiveX程序中不会执行(经验证在ProjectName+Ctrl(即整个ActiveX获得输入焦点)时PreTranslateMessage方法会执行)。
解决办法是为控件添加OnMouseMove消息响应,在OnMouseMove(UINT nFlags, CPoint point)方法中添加代码:
//构造一个MSG
MSG msg;
msg.hwnd = m_hWnd;
msg.message = WM_MOUSEMOVE;
msg.wParam = LOWORD(point.x);
msg.lParam = LOWORD(point.y);
msg.time = 0;
msg.pt.x = LOWORD(point.y);
msg.pt.y = HIWORD(point.y);
m_ToolTip.RelayEvent(&msg);
这样才会使鼠标在控件上移动时显示ToolTip,但是要求要先点选过该控件才行。如果想要更进一步去掉这个先点选控件的限制,则需要在自定义控件的父窗口中响应OnMouseMove消息,并构造MSG关联到ToolTip。此时需要注意point的坐标转换。
完整的相关代码(PTZControlWnd和BitmapSlider)如下:
父窗口PTZControlWnd:
//成员变量声明
CBitmapSlider m_bsSpeedOrStepsize;
void PTZControlWnd::OnMouseMove(UINT nFlags, CPoint point)
{
(void)nFlags;
UpdateToolTipText();//更新ToolTip文字
m_bsSpeedOrStepsize->RelayToolTipEventFromParent(point);//此处的point的坐标是相对PTZControlWnd的
VAEBaseWnd::OnMouseMove(nFlags, point);
}
控件CBitmapSlider
//成员变量声明
CToolTipCtrl m_ToolTip;
void CBitmapSlider::RelayToolTipEventFromParent(CPoint &point)
{
//将相对父窗口的坐标转换成屏幕坐标
GetParent()->ClientToScreen(&point);
//从屏幕坐标转换成相对控件自身CBitmapSlider的坐标
ScreenToClient(&point);
//因为在CBitmapSlider::OnMouseMove中也要用到,所以提取成函数
RelayToolTipEvent(point);
}
void CBitmapSlider::RelayToolTipEvent(const CPoint &point )
{
if (m_ToolTip.m_hWnd != NULL)
{
//构造一个MSG
MSG msg;
msg.hwnd = m_hWnd;
msg.message = WM_MOUSEMOVE;
msg.wParam = LOWORD(point.x);
msg.lParam = LOWORD(point.y);
msg.time = 0;
msg.pt.x = LOWORD(point.y);
msg.pt.y = HIWORD(point.y);
m_ToolTip.RelayEvent(&msg);
}
}
为整个ActiveX添加ToolTip的方法可以参考MSDN,同样没有使用PreTranslateMessage方法