Come posso visualizzare i suggerimenti personalizzati in un CTreeCtrl?
-
06-07-2019 - |
Domanda
Ho una classe derivata da CTreeCtrl
. In OnCreate ()
sostituisco l'oggetto CToolTipCtrl
predefinito con uno personalizzato:
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;
}
Il gestore dei messaggi è simile al seguente:
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &CMyTreeCtrl::OnTtnNeedText)
Tuttavia non ricevo mai un messaggio TTN_NEEDTEXT
. Ho dato un'occhiata a Spy ++ e sembra anche che questo messaggio non venga mai inviato.
Quale potrebbe essere il problema qui?
Aggiornamento
Non sono sicuro che sia rilevante: la finestra principale di CTreeCtrl
è di tipo CDockablePane
. Potrebbe esserci del lavoro extra necessario affinché questo funzioni?
Soluzione
Finalmente! L'ho (parzialmente) risolto:
Sembra che la finestra del genitore CDockablePane abbia effettivamente causato questo problema ...
Per prima cosa ho rimosso tutto il codice specifico del tooltip dalla classe derivata da CTreeCtrl. Tutto è fatto nella finestra del riquadro principale.
Quindi ho modificato il metodo OnCreate ()
della finestra principale:
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;
}
Purtroppo non possiamo semplicemente chiamare AddTool ()
con meno parametri perché la classe base si lamenterà sotto forma di un ASSERT
su un uFlag
membro se non è stato impostato alcun ID strumento.
E poiché dobbiamo impostare l'ID, dobbiamo anche impostare un rettangolo. Ho creato un membro CRect
e l'ho impostato su (0, 0, 10000, 10000)
in CTor. Non ho ancora trovato un modo di lavorare per modificare la dimensione corretta dello strumento, quindi questa è la mia soluzione molto brutta. Questo è anche il motivo per cui chiamo parziale questa soluzione. Aggiornamento: Ho fatto una domanda al riguardo.
Infine c'è il gestore per ottenere le informazioni sulla descrizione comandi:
// 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;
}
Altri suggerimenti
Credo che tu debba ancora abilitare il tooltip, anche se stai sostituendo l'integrato.
EnableToolTips(TRUE);
Bene, dal momento che non ha funzionato per te e poiché nessuno più esperto ha offerto alcun aiuto, ecco alcuni altri suggerimenti da me. Sebbene siano zoppi, potrebbero farti spostare di nuovo:
- Assicurati che il tuo rotine OnCreate () sia effettivamente eseguito.
- Abilita il suggerimento PRIMA di sostituirlo.
-
Il codice che uso per fare questo appare così. (Confesso che non capisco tutti i dettagli, l'ho copiato da un codice di esempio, ha funzionato e quindi non l'ho più guardato.)
// Abilita la descrizione comandi standard
EnableToolTips (TRUE);
// Disabilita la descrizione comandi incorporata
CToolTipCtrl * pToolTipCtrl = (CToolTipCtrl *) CWnd :: FromHandle ((HWND) :: SendMessage (m_hWnd, LVM_GETTOOLTIPS, 0, 0L));
Non ho provato in un CTreeCtrl ma penso che dovresti chiamare RelayEvent affinché il tooltip ctrl sappia quando deve essere visualizzato il tooltip. Prova questo:
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);
}
Spero che questo aiuto.
Non è necessario sovrascrivere OnToolHitTest ()?
(vecchio) Risorsa 1
(precedente) Risorsa 2:
Oltre a restituire il codice hit (nHit), devi anche compilare la struttura TOOLINFO. Ecco come lo fa VIRGIL in 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;
La maggior parte di questo è ovvio, come l'impostazione di hwnd e uId, ma in parte è meno. Ho impostato il membro retto su un rettangolo largo 2 pixel e alto 2 pixel centrato attorno alla posizione del mouse. Il controllo tooltip utilizza questo rettangolo come rettangolo di delimitazione dello strumento " " che voglio essere minuscolo, quindi spostare il mouse ovunque costituirà uno spostamento all'esterno dello strumento. Ho impostato TTF _ NOTBUTTON in uFlags perché la descrizione comando non è associata a un pulsante. Questo è un flag MFC speciale definito in afxwin.h; MFC lo utilizza per fornire assistenza per i suggerimenti. C'è un altro flag esteso MFC per tooltip, TTF _ ALWAYSTIP. È possibile utilizzarlo se si desidera che MFC visualizzi il suggerimento anche quando la finestra non è attiva. Forse avrai notato che finora non ho detto a MFC o alla descrizione comandi o al TOOLINFO quale sia il testo effettivo del suggerimento. Ecco a cosa serve LPSTR _ TEXTCALLBACK. Questo valore speciale indica al controllo tooltip (quello interno, thread-global che utilizza MFC) di richiamare la mia finestra per ottenere il testo. Lo fa inviando alla mia finestra un messaggio WM _ NOTIFY con codice di notifica TTN _ NEEDTEXT.
Prova a gestire in modo specifico tutti gli ID tooltip:
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXT, 0, 0xFFFF, &CMyTreeCtrl::OnNeedTipText)
Se non funziona, potrebbe essere necessario chiamare manualmente RelayEvent () da PreTranslateMessage ().