Comment afficher des info-bulles personnalisées dans un CTreeCtrl?
-
06-07-2019 - |
Question
J'ai une classe dérivée de CTreeCtrl
. Dans OnCreate ()
, je remplace l'objet CToolTipCtrl
par défaut par un objet personnalisé:
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;
}
Mon gestionnaire de messages ressemble à ceci:
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, &CMyTreeCtrl::OnTtnNeedText)
Cependant, je ne reçois jamais de message TTN_NEEDTEXT
. J’ai jeté un coup d’œil à Spy ++ et il semble aussi que ce message ne soit jamais envoyé.
Quel pourrait être le problème ici?
Mettre à jour
Je ne sais pas si cela est pertinent: la fenêtre parente de CTreeCtrl
est de type CDockablePane
. Pourrait-il y avoir du travail supplémentaire pour que cela fonctionne?
La solution
Enfin! Je l'ai (partiellement) résolu:
Il semble que la fenêtre parent de CDockablePane ait effectivement causé ce problème ...
D'abord, j'ai supprimé tout le code spécifique à l'info-bulle de la classe dérivée de CTreeCtrl. Tout est fait dans la fenêtre du volet parent.
J'ai ensuite modifié la méthode OnCreate ()
de la fenêtre parente:
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;
}
Malheureusement, nous ne pouvons pas simplement appeler AddTool ()
avec moins de paramètres car la classe de base se plaindra sous la forme d'un ASSERT
à propos d'un uFlag
membre s'il n'y a pas d'ID d'outil défini.
Et puisque nous devons définir l'ID, nous devons également définir un rectangle. J'ai créé un membre CRect
et l'ai défini sur (0, 0, 10000, 10000)
dans le CTor. Je n'ai pas encore trouvé de moyen efficace de changer la taille de l'outil, c'est donc ma solution très laide. C'est aussi pourquoi j'appelle cette solution partielle. Mise à jour: J'ai posé une question à ce sujet.
Enfin, il y a le gestionnaire pour obtenir les infos sur l'info-bulle:
// 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;
}
Autres conseils
Je pense que vous devez toujours activer l'info-bulle, même si vous remplacez le préréglage intégré.
EnableToolTips(TRUE);
Eh bien, puisque cela n’a pas fonctionné pour vous et qu’aucun autre expert n’a proposé d’aide, voici quelques suggestions supplémentaires de ma part. Bien qu'ils soient boiteux, ils pourraient vous faire bouger à nouveau:
- Assurez-vous que votre rotation OnCreate () est en cours d'exécution.
- Activez l'info-bulle AVANT de la remplacer.
-
Le code que j'utilise pour faire ceci ressemble à ceci. (J'avoue que je ne comprends pas tous les détails, je l'ai copié à partir d'un exemple de code, cela a fonctionné et je ne l'ai plus jamais regardé.)
// Activer l'info-bulle standard
EnableToolTips (TRUE);
// Désactiver l'info-bulle intégrée
CToolTipCtrl * pToolTipCtrl = (CToolTipCtrl *) CWnd :: FromHandle ((HWND) :: SendMessage (m_hWnd, LVM_GETTOOLTIPS, 0, 0L));;
Je n'ai pas essayé de CTreeCtrl mais je pense que vous devriez appeler RelayEvent pour que l'infobulle ctrl indique le moment où l'info-bulle doit être affichée. Essayez ceci:
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);
}
J'espère cette aide.
Ne devez-vous pas écraser OnToolHitTest ()?
(ancienne) ressource 1
(ancienne) Ressource 2:
En plus de renvoyer le code d'accès (nHit), vous devez également renseigner la structure TOOLINFO. Voici comment VIRGIL le fait dans 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 plupart de ces opérations sont évidentes, comme le réglage de hwnd et uId & # 8212; mais certaines le sont moins. Je règle le membre rect sur un rectangle de 2 pixels de large et 2 pixels de haut, centré autour de l'emplacement de la souris. Le contrôle d'info-bulle utilise ce rectangle comme rectangle de délimitation de "l'outil". que je veux être petit, alors déplacer la souris n’importe où constituera un déplacement hors de l’outil. J'ai défini TTF _ NOTBUTTON dans uFlags car l'info-bulle n'est pas associée à un bouton. Il s'agit d'un indicateur MFC spécial défini dans afxwin.h; MFC l'utilise pour faire de l'aide pour les info-bulles. Il existe un autre indicateur étendu MFC pour les info-bulles, TTF _ ALWAYSTIP. Vous pouvez l'utiliser si vous souhaitez que le MFC affiche le conseil même lorsque votre fenêtre n'est pas active. Vous avez peut-être remarqué que, jusqu'à présent, je n'ai pas communiqué à MFC, à l'infobulle ou à TOOLINFO le texte de cette astuce. C’est ce à quoi sert LPSTR _ TEXTCALLBACK. Cette valeur spéciale indique au contrôle info-bulle (le contrôle interne global de thread que MFC utilise) de rappeler ma fenêtre pour obtenir le texte. Pour ce faire, il envoie à ma fenêtre un message WM _ NOTIFY avec le code de notification TTN _ NEEDTEXT.
Essayez de gérer spécifiquement tous les identifiants d'infobulle:
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXT, 0, 0xFFFF, &CMyTreeCtrl::OnNeedTipText)
Si cela ne fonctionne pas, vous devrez peut-être appeler manuellement RelayEvent () à partir de PreTranslateMessage ().