Hello all,
I am trying to draw a decorator around my cursor when the user has a certain key pressed.
bool Example::_DrawDecoration(IndexedViewportR viewport) { if(!mdlWindow_isView (nullptr, statedata.current.gwP)) return false; //MstnTool::GetCurrentMstnButtonEvent (MstnButtonEvent *ev) if(statedata.current.qualifierMask == 4) { auto output = viewport.GetIViewOutput(); output->SetSymbology(DgnPlatform::Viewport::MakeTrgbColor(200,200,200, 128), DgnPlatform::Viewport::MakeTrgbColor(200,200,200, 128), 1, 0); DEllipse3d ellipse = DEllipse3d::FromCenterRadiusXY(statedata.current.dpUors, 10000.0); output->DrawArc3d(ellipse, true, true, NULL); } return true; //Bentley Note: A handful of internal implementations return true for a very specific purpose. // External implementations such as your own should always return false. // My Note: This needs to be true, otherwise the _draw method is not called when in a dynamic tool... Ex: Create Line }
The decorator is working fine with the exception that when i let go of the key, the ellipse is still displayed until the cursor is moved again.
Also, when I first press the key, the ellipse does not show until the cursor is moved.
Currently, I have set a callback using SystemCallback::SetWindowsKeystrokeMessageFunction to notify me when the user has pressed \ unpressed the key, however I have not had any luck getting the view decoration to refresh.
I have tried setting Viewport.SetNeedsRefresh() and IndexedViewSet.UpdateView(), however neither of these seem to update the decorations, only transients.
Any suggestions would be great!
Thanks
Maury said:I have tried setting Viewport.SetNeedsRefresh()
This should be all you need. This will cause your _DrawDecoration method to be called for this Viewport, and assuming you don't draw anything, your decoration graphics go away.
Seems like your code could use an additional check that IndexedViewport for _DrawDecoration is actually the one the cursor is in though...
-B
Answer Verified By: Maury
Hi Brien,
Thanks for the reply.
I am calling SetNeedsRefresh() on all of the views trying to get it to work. Nothing happens with the decoration
SystemCallback::SetWindowsKeystrokeMessageFunction([](void* windowID, UInt32 messageNumber, uintptr_t wParam, intptr_t lParam, long x, long y) { if(messageNumber != 0x100 && messageNumber != 0x101) return false; printf("Key pressed %d\n", wParam); if(messageNumber == 0x101) { //DgnPlatform::IndexedViewSet::FullUpdateInfo updateInfo; //updateInfo.SetDoBackingStore(true); //updateInfo.SetIncremental(false); IndexedViewSetR viewSet = DgnPlatform::IViewManager::GetActiveViewSet(); for (auto& viewport : viewSet) { printf("Refreshing view: %d\n", viewport->GetViewNumber()); viewport->SetNeedsRefresh(); //viewSet.UpdateView(viewport, DgnPlatform::DRAW_MODE_Normal, DgnPlatform::DrawPurpose::Update, updateInfo); } } return false; });
Brien Bastings said:and assuming you don't draw anything, your decoration graphics go away.
Actually, you may be on to something here. It is possible the decoration is still detecting the button as pressed. Will look into this.
Have you got this working? What is your solution?
Regards, Jon Summers LA Solutions
Hi Jon,
I was not able to figure out a full working solution to what I am trying to do..
I also I had to stop relying on statedata in _DrawDecoration because that only updates if you move your cursor.. so the qualifier key was not updating when your cursor was stationary.
The decorator now refreshes when I press\unpress the key, which is great.........
But it only works when you are in a tool that has not started its dynamics....
After a tool (Ex: Create Line) accepts a click and begins its dynamics, the decorator stops responding to "SetNeedsRefresh()" and will not show\hide the decorator unless I move the cursor.
I have about given up on this experiment, but let me know if you make any progress
The below example is hard coded for the Shift key.
#include "CursorDecorator.h" /* * * if the decorator needs to display something different from the last time it was called. * Tools with decorations based on the cursor location might call Viewport::SetNeedsRefresh from * the DgnTool::_OnModelMotion event. * */ bool CursorDecorator::_ButtonPressed = false; /** * \brief Draw the view decorations * \param viewport viewport being drawn too * \return false, not documented on why.. */ bool CursorDecorator::_DrawDecoration(IndexedViewportR viewport) { if(!mdlWindow_isView (nullptr, statedata.current.gwP)) return false; if(_ButtonPressed) // && !mdlLocate_getCurrentToolState() Add this so that the decorator will not show when in "Locate" mode { double windowSize = 10000.0; auto output = viewport.GetIViewOutput(); output->SetSymbology(DgnPlatform::Viewport::MakeTrgbColor(200,200,200, 128), DgnPlatform::Viewport::MakeTrgbColor(200,200,200, 128), 1, 0); DEllipse3d ellipse = DEllipse3d::FromCenterRadiusXY(statedata.current.dpUors, windowSize); output->DrawArc3d(ellipse, true, true, NULL); } return true; //Bentley Note: A handful of internal implementations return true for a very specific purpose. // External implementations such as your own should always return false. // However, this needs to be true, otherwise the _draw method is not called when in a dynamic tool... Ex: Create Line } /** * \brief Ctor which adds the view decoration to MicroStations view manager */ CursorDecorator::CursorDecorator() { _ButtonPressed = false; SystemCallback::SetWindowsKeystrokeMessageFunction([](void* windowID, UInt32 messageNumber, uintptr_t wParam, intptr_t lParam, long x, long y) { if(messageNumber != 0x100 && messageNumber != 0x101) return false; if(messageNumber == 0x101 && wParam == 16 && _ButtonPressed) { if(_ButtonPressed) // && !mdlLocate_getCurrentToolState()) Add this so that the decorator will not show when in "Locate" mode { IndexedViewSetR viewSet = DgnPlatform::IViewManager::GetActiveViewSet(); for (auto& viewport : viewSet) { if(viewport->GetViewNumber() != statedata.current.view) continue; viewport->SetNeedsRefresh(); } printf("Forcing Redraw\n"); } _ButtonPressed = false; } else if(messageNumber == 0x100 && wParam == 16 && !_ButtonPressed)// && !mdlLocate_getCurrentToolState()) Add this so that the decorator will not show when in "Locate" mode { if(!_ButtonPressed) { IndexedViewSetR viewSet = DgnPlatform::IViewManager::GetActiveViewSet(); for (auto& viewport : viewSet) { if(viewport->GetViewNumber() != statedata.current.view) continue; viewport->SetNeedsRefresh(); } printf("Forcing Redraw\n"); } _ButtonPressed = true; } printf("Key Status %s\n", _ButtonPressed ? "true" : "false"); return false; }); } void CursorDecorator::Attach() { DgnPlatform::IViewManager::GetManager().AddViewDecoration(this); } void CursorDecorator::Detach() { DgnPlatform::IViewManager::GetManager().DropViewDecoration(this); } /** * \brief Dtor which drops the view decoration from MicroStations view manager */ CursorDecorator::~CursorDecorator() = default;
#pragma once #include <Mstn\MdlApi\MdlApi.h> /** * \brief An implementation of the DgnPlatform::IViewDecoration interface */ class CursorDecorator : public DgnPlatform::IViewDecoration { protected: bool _DrawDecoration(IndexedViewportR viewport) override; public: static CursorDecorator& Instance() { static CursorDecorator instance; return instance; } void Attach(); void Detach(); private: CursorDecorator(); ~CursorDecorator(); static bool _ButtonPressed; };