我有一个派生自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
类型。这需要一些额外的工作吗?
答案 0 :(得分: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;
}
不幸的是,我们不能简单地使用较少的参数调用AddTool()
,因为如果没有设置工具ID,基类会以ASSERT
的形式抱怨uFlag
成员。
由于我们需要设置ID,我们还需要设置一个矩形。我创建了一个CRect
成员并将其设置为CTor中的(0, 0, 10000, 10000)
。我还没有找到一种改变工具的矩形大小的工作方式,所以这是我非常难看的解决方法。这也是我将此解决方案称为部分原因的原因。 更新:I asked a question regarding this.
最后有一个获取工具提示信息的处理程序:
// 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;
}
答案 1 :(得分:4)
我相信你仍然需要启用工具提示,即使你要更换内置。
EnableToolTips(TRUE);
好吧,既然这对你不起作用,而且没有更多的专家提供任何帮助,这里还有一些建议。虽然他们很蹩脚,但他们可能会让你再次感动:
我用来做这个的代码看起来像这样。 (我承认我不了解所有细节,我从一些示例代码复制它,它工作,所以我再也没有看过它了。)
//启用标准工具提示
EnableToolTips(TRUE);
//禁用内置工具提示
CToolTipCtrl * pToolTipCtrl =(CToolTipCtrl *)CWnd :: FromHandle((HWND):: SendMessage(m_hWnd,LVM_GETTOOLTIPS,0,0L));
答案 2 :(得分:1)
我没有在CTreeCtrl中尝试过,但我认为应该使用工具提示ctrl调用RelayEvent来了解何时必须显示工具提示。试试这个:
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);
}
我希望这有帮助。
答案 3 :(得分:1)
您是否必须覆盖OnToolHitTest()?
(old) Resource 1
(old) Resource 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消息来完成此操作。
答案 4 :(得分:0)
尝试专门处理所有工具提示ID:
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXT, 0, 0xFFFF, &CMyTreeCtrl::OnNeedTipText)
如果这不起作用,您可能必须从PreTranslateMessage()手动调用RelayEvent()。