在CScrollView中跟踪工具提示?

时间:2017-08-08 22:18:38

标签: c++ mfc tooltip mdi docview

在标准C ++ / MFC MDI文档/视图项目中,我想在视图中实现跟踪工具提示(通常占据大部分主框架窗口的选项卡式视图窗口)。因此,在课程MyAppView中,我有一个成员CToolTipCtrl tooltip。函数MyAppView::OnInitialUpdate()包含初始化

BOOL ok0 = tooltip.Create(this, TTS_ALWAYSTIP);
CRect clientRect; GetClientRect(&clientRect);
BOOL ok2 = tooltip.AddTool(this, LPSTR_TEXTCALLBACK, &clientRect, 1234/*tool ID*/);
tooltip.Activate(TRUE);

使视图的整个客户区域成为“工具”。消息映射包含一个条目

ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnNeedToolTipText)

,函数OnNeedToolTipText定义为

BOOL MyAppView::OnNeedToolTipText(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{
    UNREFERENCED_PARAMETER(id);

    NMTTDISPINFO *pTTT = (NMTTDISPINFO *)pNMHDR;
    UINT_PTR nID = pNMHDR->idFrom;
    BOOL bRet = FALSE;
    if(nID == 1234)
    {
        // Come here when text is needed for tracking tooltip
    }
    if(pTTT->uFlags & TTF_IDISHWND)
    {
        // idFrom is actually the HWND of the tool
        nID = ::GetDlgCtrlID((HWND)nID);
        if(nID)
        {
            _stprintf_s(pTTT->szText, sizeof(pTTT->szText) / sizeof(TCHAR),
              _T("Control ID = %d"), nID);
            pTTT->hinst = AfxGetResourceHandle();
            bRet = TRUE;
        }
    }

    *pResult = 0;

    return bRet;
}

只会将鼠标放在菜单项(文件,编辑,视图,窗口,帮助)上会导致代码输入OnNeedToolTipText,ID为0-5。将鼠标移动到客户区(视图)不会做任何事情。

如何才能让工具提示只显示在视图的客户区?

Visual Studio 2017; C ++; 64位Windows 7

4 个答案:

答案 0 :(得分:0)

要解决此问题,您需要执行以下操作:

BOOL CMyAppView::PreTranslateMessage(MSG* pMsg)
{
    switch (pMsg->message)
    {
    case WM_KEYDOWN:
    case WM_SYSKEYDOWN:
    case WM_LBUTTONDOWN:
    case WM_RBUTTONDOWN:
    case WM_MBUTTONDOWN:
    case WM_LBUTTONUP:
    case WM_RBUTTONUP:
    case WM_MBUTTONUP:
    case WM_MOUSEMOVE:
        if (m_pToolTip->GetSafeHwnd () != NULL)
        {
            m_pToolTip->RelayEvent(pMsg);
        }
        break;
    }

    return CScrollView::PreTranslateMessage(pMsg);
}

答案 1 :(得分:0)

如果您想在视图中使用跟踪工具提示,请按以下步骤操作:

创建工具提示并添加工具。

void CToolTipDemoView::OnInitialUpdate()
{
    // ...

    m_toolTip.Create(this, TTS_ALWAYSTIP | TTS_NOANIMATE);
    m_toolTip.AddTool(this, _T("Doesn't matter"));
}

处理WM_MOUSEMOVE消息。首先,调用_TrackMouseEvent以进一步接收WM_MOUSELEAVE并激活工具提示。其次,更新工具提示文本,并在鼠标指针坐标处显示它。

void CToolTipDemoView::OnMouseMove(UINT nFlags, CPoint point)
{
    if (!m_bTrackingMouseLeave)
    {
        TRACKMOUSEEVENT tme = { 0 };
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_LEAVE;
        tme.hwndTrack = m_hWnd;
        ::_TrackMouseEvent(&tme);

        m_toolTip.Activate(TRUE);
        m_bTrackingMouseLeave = TRUE;
    }

    if (m_pointLastMousePos != point)
    {
        CString strText;
        strText.Format(_T("x = %d y = %d"), point.x, point.y);
        m_toolTip.UpdateTipText(strText, this);
        m_toolTip.Popup();
        m_pointLastMousePos = point;
    }

    CScrollView::OnMouseMove(nFlags, point);
}

处理WM_MOUSELEAVE并停用工具提示。

void CCToolTipDemoView::OnMouseLeave()
{
    m_bTrackingMouseLeave = FALSE;

    // mouse pointer leaves the window so deactivate the tooltip
    m_toolTip.Activate(FALSE);

    CScrollView::OnMouseLeave();
}

注意:

  • 没有必要处理TTN_NEEDTEXT。
  • 此外,没有必要覆盖PreTranslateMessage

答案 2 :(得分:0)

所以我回去看看我可能会失踪的东西。我在十多年前写过这些东西。我还覆盖了一个CWnd成员

virtual INT_PTR OnToolHitTest( CPoint point, TOOLINFO* pTI ) const;

使用:

INT_PTR HERichView::OnToolHitTest( CPoint point, TOOLINFO* pTI ) const
{
    pTI->hwnd = m_hWnd;
    pTI->uId = point.x + ( point.y << 16 );
    CRect rect;
    GetClientRect( rect );
    pTI->rect= rect;
    pTI->lpszText= LPSTR_TEXTCALLBACK;
    return pTI->uId;
}

我查了一下,如果没有这个,它就不会工作。所以你的:

ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTip )

如果添加以上内容,应该被调用。并且只需要EnableToolTips( );

答案 3 :(得分:0)

我没有成功使跟踪工具提示在MFC中工作。我最接近的是

在留言地图中:ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnNeedToolTipText)

OnInitialUpdateBOOL ok1 = EnableTrackingToolTips(TRUE);

覆盖虚拟函数OnToolHitTest

    pTI->hwnd = m_hWnd;
    pTI->uId = (UINT_PTR)m_hWnd;
    pTI->uFlags = TTF_IDISHWND | TTF_ALWAYSTIP | TTF_TRACK | TTF_NOTBUTTON | TTF_ABSOLUTE | TTF_SUBCLASS;
    pTI->lpszText = LPSTR_TEXTCALLBACK;
    return pTI->uId;

OnNeedToolTipText

NMTTDISPINFO *pTTT = (NMTTDISPINFO *)pNMHDR;
UINT_PTR nID = pNMHDR->idFrom;
BOOL bRet = FALSE;
if(pTTT->uFlags & TTF_IDISHWND)
{
    // idFrom is actually the HWND of the tool
    nID = ::GetDlgCtrlID((HWND)nID);
    if(nID)
    {
        CURSORINFO ci; ci.cbSize = sizeof(CURSORINFO); // get something interesting to display
        GetCursorInfo(&ci);
        _stprintf_s(pTTT->szText, sizeof(pTTT->szText) / sizeof(TCHAR),
            _T("Control ID = %lld at (%d, %d)"), nID, ci.ptScreenPos.x, ci.ptScreenPos.y);
        pTTT->hinst = AfxGetResourceHandle();
        bRet = TRUE;
    }
}
*pResult = 0;
return bRet;

这会产生以下特殊行为。当我启动应用程序并将鼠标光标移动到CScrollView的客户区域时,光标旁边会出现一个工具提示。

如果我小心地(平滑地)移动鼠标,工具提示会正确跟踪。但是过了一会儿,它消失了,没有进一步的鼠标动作,包括离开CScrollView窗口并返回,让它重新出现。

我认为发生的事情是当鼠标光标移动到工具提示窗口上时,工具提示将永久关闭。这种消失似乎与时间无关(例如,由于自动弹出);如果鼠标保持不变,工具提示将无限期保留。