3

我有一个派生自CTreeCtrl. 在OnCreate()我用自定义对象替换默认CToolTipCtrl对象:

int CMyTreeCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CTreeCtrl::OnCreate(lpCreateStruct) == -1)
        return -1;

    // Replace tool tip with our own which will
    // ask us for the text to display with a TTN_NEEDTEXT message
    CTooltipManager::CreateToolTip(m_pToolTip, this, AFX_TOOLTIP_TYPE_DEFAULT);
    m_pToolTip->AddTool(this, LPSTR_TEXTCALLBACK);
    SetToolTips(m_pToolTip);

    // Update: Added these two lines, which don't help either
    m_pToolTip->Activate(TRUE);
    EnableToolTips(TRUE);
    
    return 0;
}

我的消息处理程序如下所示:

ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &CMyTreeCtrl::OnTtnNeedText)

但是我从来没有收到过TTN_NEEDTEXT消息。我看了一下 Spy++,看起来这条消息永远不会被发送。

这里可能是什么问题?

更新

我不确定这是否相关:CTreeCtrl的父窗口类型为CDockablePane。是否需要一些额外的工作才能使其正常工作?

4

5 回答 5

5

最后!我(部分)解决了它:

看起来 CDockablePane 父窗口确实导致了这个问题......

首先,我从 CTreeCtrl 派生类中删除了所有工具提示特定的代码。一切都在父窗格窗口中完成。

然后我编辑了父窗口的OnCreate()方法:

int CMyPane::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CDockablePane::OnCreate(lpCreateStruct) == -1)
        return -1;

const DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
    TVS_CHECKBOXES | TVS_DISABLEDRAGDROP | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT |
    TVS_INFOTIP | TVS_NOHSCROLL | TVS_SHOWSELALWAYS;

// TREECTRL_ID is a custom member constant, set to 1
if(!m_tree.Create(dwStyle, m_treeRect, this, TREECTRL_ID ) )
{
    TRACE0("Failed to create trace tree list control.\n");
    return -1;
}

// m_pToolTip is a protected member of CDockablePane
m_pToolTip->AddTool(&m_tree, LPSTR_TEXTCALLBACK, &m_treeRect, TREECTRL_ID);
m_tree.SetToolTips(m_pToolTip);


return 0;

}

不幸的是,我们不能简单地用更少的参数调用,因为如果没有设置工具 ID AddTool(),基类将以关于成员的形式抱怨ASSERTuFlag而且由于我们需要设置ID,所以我们还需要设置一个矩形。我创建了一个CRect成员并将其设置为(0, 0, 10000, 10000)CTor。我还没有找到改变工具矩形大小的工作方法,所以这是我非常丑陋的解决方法。这也是我将此解决方案称为部分解决方案的原因。更新:我问了一个关于这个的问题。

最后是获取工具提示信息的处理程序:

// Message map entry
ON_NOTIFY(TVN_GETINFOTIP, TREECTRL_ID, &CMobileCatalogPane::OnTvnGetInfoTip)


// Handler
void CMyPane::OnTvnGetInfoTip(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMTVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMTVGETINFOTIP>(pNMHDR);

    // This is a CString member
    m_toolTipText.ReleaseBuffer();
    m_toolTipText.Empty();

    // Set your text here...

    pGetInfoTip->pszText = m_toolTipText.GetBuffer();

    *pResult = 0;
}
于 2009-05-15T09:05:15.447 回答
4

我相信您仍然必须启用工具提示,即使您要替换内置。

EnableToolTips(TRUE);

好吧,既然这对你不起作用,而且没有其他专家提供任何帮助,这里还有一些我的建议。虽然它们很蹩脚,但它们可能会让你再次动起来:

  • 确保您的 OnCreate() rotine 实际正在执行。
  • 在更换之前启用工具提示。
  • 我用来执行此操作的代码如下所示。(我承认我不了解所有细节,我从一些示例代码中复制了它,它有效,所以我再也没有看过它。)

    // 启用标准工具提示

    启用工具提示(真);

    // 禁用内置工具提示

    CToolTipCtrl* pToolTipCtrl = (CToolTipCtrl*)CWnd::FromHandle((HWND)::SendMessage(m_hWnd, LVM_GETTOOLTIPS, 0, 0L));

于 2008-11-06T19:01:20.137 回答
1

我没有在 CTreeCtrl 中尝试过,但我认为您应该调用 RelayEvent 以获取工具提示 ctrl 以了解何时必须显示工具提示。试试这个:

MyTreeCtrl.h:

virtual BOOL PreTranslateMessage(MSG* pMsg);

MyTreeCtrl.cpp:

BOOL CMyTreeCtrl::PreTranslateMessage(MSG* pMsg) 
{
    m_pToolTip.Activate(TRUE);
    m_pToolTip.RelayEvent(pMsg);

    return CTreeCtrl::PreTranslateMessage(pMsg);
}

我希望这会有所帮助。

于 2008-11-09T00:06:53.593 回答
1

您不必重写 OnToolHitTest() 吗?

(旧)资源 1

(旧)资源 2:

除了返回命中代码 (nHit) 之外,您还必须填写 TOOLINFO 结构。下面是 VIRGIL 在 CMainFrame::OnToolHitTest 中的做法:

 int nHit = MAKELONG(pt.x, pt.y);
 pTI->hwnd = m _ hWnd;
 pTI->uId  = nHit;
 pTI->rect = CRect(CPoint(pt.x-1,pt.y-1),CSize(2,2));
 pTI->uFlags |= TTF _ NOTBUTTON;
 pTI->lpszText = LPSTR _ TEXTCALLBACK;

其中大部分是显而易见的——比如设置 hwnd 和 uId——但其中一些不是那么明显。我将 rect 成员设置为以鼠标位置为中心的 2 像素宽、2 像素高的矩形。工具提示控件使用这个矩形作为“工具”的边界矩形,我希望它很小,所以将鼠标移动到任何地方都会构成在工具之外移动。我在 uFlags 中设置了 TTF _ NOTBUTTON,因为工具提示与按钮无关。这是 afxwin.h 中定义的特殊 MFC 标志;MFC 使用它为工具提示提供帮助。工具提示还有另一个 MFC 扩展标志,TTF_ALWAYSTIP。如果您希望 MFC 即使在您的窗口未处于活动状态时也显示提示,您可以使用它。您可能已经注意到,到目前为止,我还没有告诉 MFC 或工具提示或 TOOLINFO 提示的实际文本是什么。这就是 LPSTR _ TEXTCALLBACK 的用途。这个特殊值告诉工具提示控件(MFC 使用的内部线程全局控件)调用我的窗口以获取文本。它通过向我的窗口发送一条带有通知代码 TTN_NEEDTEXT 的 WM_NOTIFY 消息来做到这一点。

于 2009-04-28T18:55:38.910 回答
0

尝试专门处理所有工具提示 ID:

ON_NOTIFY_EX_RANGE(TTN_NEEDTEXT, 0, 0xFFFF, &CMyTreeCtrl::OnNeedTipText)

如果这不起作用,您可能必须从 PreTranslateMessage() 手动调用 RelayEvent()。

于 2008-11-08T05:31:13.627 回答