Context: I have built a scene with several actors to present two rooms and the components in MFC program, and I want to implement a function: I can print some message to identify components when I put my cursor in the item for a while. I tried to use vtkballoonwidget to do it, and it works but whenever I resize the current window the event WM_MOUSEHOVER would never be detected anymore.
Here some codes related:
CMFCApplicationVtkView.h:
class CMFCApplicationVtkView : public CView
{
public:
vtkSmartPointer renderer ;
//vtkMFCrenderwindow
vtkSmartPointer renWin ;
vtkSmartPointer iren;
vtkSmartPointer<PickCallback> pickCallback;
vtkSmartPointer<vtkPropPicker> picker;
vtkSmartPointer<customIteractorStyle> style;
vtkSmartPointer<vtkBalloonWidget> balloonWidget;
bool m_bMouseTracking;
///
/// ///////////////////
///
protected: // création à partir de la sérialisation uniquement
CMFCApplicationVtkView() noexcept;
DECLARE_DYNCREATE(CMFCApplicationVtkView)
// Attributs
public:
CMFCApplicationVtkDoc* GetDocument() const;
// Opérations
public:
// Substitutions
public:
virtual void OnDraw(CDC* pDC); // substitué pour dessiner cette vue
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
// Implémentation
public:
virtual ~CMFCApplicationVtkView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Fonctions générées de la table des messages
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
virtual void OnInitialUpdate();
afx_msg void OnNewmenuTest1();
afx_msg void OnUpdateNewmenuTest1(CCmdUI* pCmdUI);
afx_msg void OnAffichageTest2();
afx_msg void OnSize(UINT nType, int cx, int cy);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
// afx_msg void OnClose();
afx_msg void OnMouseHover(UINT nFlags, CPoint point);
afx_msg void OnMouseLeave();
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
};
CMFCApplicationVtkView.cpp
LRESULT CMFCApplicationVtkView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: ajoutez ici votre code spécialisé et/ou l’appel de la classe de base
switch (message)
{
case WM_MOUSEMOVE:
if (!m_bMouseTracking)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.hwndTrack = m_hWnd;
tme.dwHoverTime = HOVER_DEFAULT;
m_bMouseTracking = TrackMouseEvent(&tme);
}
if (this->iren->GetInitialized())
{
return vtkHandleMessage2(this->m_hWnd, message, wParam, lParam, this->iren);
}
break;
case WM_MOUSEHOVER:
if (this->iren->GetInitialized())
{
m_bMouseTracking = false;
return vtkHandleMessage2(this->m_hWnd, message, wParam, lParam, this->iren);
}
break;
case WM_MOUSELEAVE:
if (this->iren->GetInitialized())
{
m_bMouseTracking = false;
return vtkHandleMessage2(this->m_hWnd, message, wParam, lParam, this->iren);
}
break;
case WM_SIZE:
if (!m_bMouseTracking)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.hwndTrack = m_hWnd;
tme.dwHoverTime = HOVER_DEFAULT;
m_bMouseTracking = TrackMouseEvent(&tme);
}
if (this->iren->GetInitialized())
{
return vtkHandleMessage2(this->m_hWnd, message, wParam, lParam, this->iren);
}
break;
case WM_PAINT:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_CHAR:
case WM_TIMER:
case WM_MOUSEWHEEL:
if (this->iren->GetInitialized())
{
return vtkHandleMessage2(this->m_hWnd, message, wParam, lParam, this->iren);
}
break;
}
return CView::WindowProc(message, wParam, lParam);
}
void CMFCApplicationVtkView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: ajoutez ici le code de votre gestionnaire de messages
CRect rect;
this->GetClientRect(&rect);
this->renWin->SetSize(rect.Width(), rect.Height()); // dimi4
if (this->iren->GetInitialized())// dimi4
{
this->iren->SetSize(rect.right - rect.left, rect.bottom - rect.top);//(cx,cy);
this->iren->UpdateSize(rect.right - rect.left, rect.bottom - rect.top);
}
//// Reset mouse tracking after resizing
//if (!m_bMouseTracking)
//{
// TRACKMOUSEEVENT tme;
// tme.cbSize = sizeof(TRACKMOUSEEVENT);
// tme.dwFlags = TME_HOVER | TME_LEAVE;
// tme.hwndTrack = m_hWnd;
// tme.dwHoverTime = HOVER_DEFAULT;
// m_bMouseTracking = TrackMouseEvent(&tme);
//}
}
void CMFCApplicationVtkView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: ajoutez ici votre code spécialisé et/ou l'appel de la classe de base
this->renWin->WindowInitialize();
CInformationLocal* pInfoLocal = new CInformationLocal((CMFCApplicationVtkView*)this);
/*pInfoLocal->CreateLocal(ID_SOL);
pInfoLocal->CreateLocal(ID_PLAFOND);
pInfoLocal->CreateLocal(ID_MF);
pInfoLocal->CreateLocal(ID_MO);*/
//pInfoLocal->CreateLocal(ID_SOLA);
//
//pInfoLocal->CreateLocal(ID_SEPARATIF);
for (int i = ID_SOLA; i < ID_COUNT; i++) {
pInfoLocal->CreateLocal((TYPE_OBJET_LOCAL)i);
}
/// <summary>
/// ////////////////////////////////////
/// </summary>
////style->SetFixedAxesActor(axes);
//iren->SetInteractorStyle(style); //24/04/2023
// Create the widget.
auto balloonRep = vtkSmartPointer<vtkBalloonRepresentation>::New();
balloonRep->SetBalloonLayoutToImageRight();
balloonWidget = vtkSmartPointer<vtkBalloonWidget>::New();
balloonWidget->SetInteractor(this->iren);
balloonWidget->SetRepresentation(balloonRep);
//balloonWidget->AddBalloon(sphereActor.GetPointer(), "This is a sphere", nullptr);
vtkSmartPointer<vtkActorCollection> actors = renderer->GetActors();
vtkActor* current_actor;
actors->InitTraversal();
while (current_actor = actors->GetNextActor()) {
std::string strIntitule = (static_cast<MyActor*>(current_actor))->GetActorName();
balloonWidget->AddBalloon(current_actor, strIntitule.c_str(), nullptr);
}
balloonWidget->EnabledOn();
/*vtkSmartPointer<vtkActorCollection> actors = renderer->GetActors();
vtkSmartPointer<vtkActor> current_actor;
actors->InitTraversal();
while (current_actor = actors->GetNextActor()) {
auto edges = vtkSmartPointer<vtkExtractEdges>::New();
edges->SetInputData(current_actor->GetMapper()->GetInput());
edges->Update();
auto edges_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
edges_mapper->SetInputData(edges->GetOutput());
auto edges_actor = vtkSmartPointer<vtkActor>::New();
edges_actor->SetMapper(edges_mapper);
edges_actor->GetProperty()->SetColor(0.75, 0.75, 0.75);
edges_actor->GetProperty()->SetOpacity(1.0);
renderer->AddActor(edges_actor);
}*/
pInfoLocal->HighLightEdge();
vtkSmartPointer<vtkNamedColors> colors = vtkSmartPointer<vtkNamedColors>::New();
renderer->SetBackground(colors->GetColor3d("Cornsilk").GetData());
}
If u want more information let me know, thanks for your help.