.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to detect zoom

12 REPLIES 12
Reply
Message 1 of 13
dubinskyv
852 Views, 12 Replies

How to detect zoom

I need to be able to detect when a user zoomed in/out and then take some action. I can do this using a CommandEnded reactor and watch for the ZOOM command and this works, but how do I detect a user scrolling the Intellimouse wheel to zoom in and out? My reactor doesn't get activated on the mouse wheel movement. Any help will be greatly appreciated.

Vadim
12 REPLIES 12
Message 2 of 13
dubinskyv
in reply to: dubinskyv

Still would like some help if anyone has any ideas. Thanks.
Message 3 of 13
PowerKiKi2
in reply to: dubinskyv

Hi,

I got the same problem as you. Did you find a way to solve that ?

Thanks,
Message 4 of 13
PowerKiKi2
in reply to: dubinskyv

I found out some dirty solution. So for the record I post it here.

First of all Toni Tanzillo mentionned AcEditorReactor::viewChanged() method in this post: http://discussion.autodesk.com/thread.jspa?messageID=5996144 . Unfortunately I couldn't find the wrapper in .NET API (neither in 2008 nor 2009). So I had to find something else.

I came across this post: http://discussion.autodesk.com/thread.jspa?messageID=392828 . They talk about system variables VIEWCTR and VIEWSIZE. The problem is these variable can not be retrieved through sysVarChanged() Editor reactor as stated by Tony Tanzillo. Nor could be used CommandEnded() as pan and zoom with mouse doesn't fires theses events.

So I chose to use some events which is very frequently fired to check if the two sysvars changed. This basically the code I came up with:


class SquareLoader
{
Point3d oldCenter;
double oldSize;

public SquareLoader()
{
Application.DocumentManager.MdiActiveDocument.Editor.PointMonitor += new Autodesk.AutoCAD.EditorInput.PointMonitorEventHandler(Editor_PointMonitor);
}

void Editor_PointMonitor(object sender, Autodesk.AutoCAD.EditorInput.PointMonitorEventArgs e)
{
Point3d center = (Point3d)Application.GetSystemVariable(@"VIEWCTR");
double size = (double)Application.GetSystemVariable(@"VIEWSIZE");

if (center != oldCenter || size != this.oldSize)
{
System.Diagnostics.Debug.WriteLine(string.Format(@"changed: VIEWCTR={0} VIEWSIZE={1}", center, size));
this.oldCenter = center;
this.oldSize = size;

// Do some stuff ...
}
}
}


Anyway if any of you guys ave a better solution (more lightweight), I'll be glad to try it. Till then I'll stick with that.
Message 5 of 13
SesticM
in reply to: dubinskyv

Funny, it's 2009 and I still didn't solve this issue. The other "dirty" solution, apart from PointMonitor, relies on a timer which compares previous and current VIEWCTR sysvars in it's handler... It's becoming more complex when it comes to MDI, viewports, etc. Truly bad solution indeed 🙂
Message 6 of 13
PowerKiKi2
in reply to: dubinskyv

Happy new year !
I wish every new year saw a new, easier to use API version. But instead I feel like they keep adding clumsy features.

Anyway I still use the method described above. However I actually need to know the exact size of the view, but I could not find a way to do that. Any idea about that ?

So far I used this approximation:

// Calculate the displayed area.
// This is not accurate as the size used is actually the height of the display. If the display is not squared, that may lead to invisible objects for end-user.
// TODO fix it by finding the real size.
Extents2d extents = new Extents2d(center.X - (size / 2), center.Y - (size / 2), center.X + (size / 2), center.Y + (size / 2));
Message 7 of 13
bikelink
in reply to: dubinskyv

I think some kind of this..

[DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedCoordFromPixelToWorld@@YAHHVCPoint@@QAN@Z")]
extern static bool acedCoordFromPixelToWorld(int viewportNumber, System.Drawing.Point pixel, out Autodesk.AutoCAD.Geometry.Point3d worldPt);


BOOL res = acedCoordFromPixelToWorld(windnum,point,ptOut);
if (res)
p3d = AcGePoint3d(ptOut[0],ptOut[1],ptOut[2]);


but the question is... where can we find the pixel of our viewport ?? 🙂
Message 8 of 13
PowerKiKi2
in reply to: dubinskyv

From the signature, I guess that function "translate" a pixel on the screen to a coordinate in th the drawing. So I guess you would call this method twice, with bottom-left and top-right pixel. That would give you the area of the drawing currently displayed.

However, as you mentionned, I don't know of any way to get the two interesting pixels...

I used to have this "prototype" code, but somehow I never could make it work:

{code}

// This code was meant to get the real displayed area.
using (Transaction transaction = Application.DocumentManager.MdiActiveDocument.TransactionManager.StartTransaction())
{
ViewportTable viewportTable = (ViewportTable)transaction.GetObject(Application.DocumentManager.MdiActiveDocument.Database.ViewportTableId, OpenMode.ForRead);
ObjectId viewportId = viewportTable["*Active"];
if (viewportId.IsNull)
{
log.Debug("Could not find active Viewport");
return;
}
ViewportTableRecord viewport = (ViewportTableRecord)transaction.GetObject(viewportId, OpenMode.ForRead);
log.Debug(string.Format("Viewport: center={0} height={1} width={2}", viewport.CenterPoint, viewport.Height, viewport.Width));
}
{code}
Message 9 of 13
bobbydehero
in reply to: dubinskyv

PowerKiKi -

I've learned from experience that your sample code will only work for paperspace viewports in SDI... maybe not that useful 😉
To make it work also in modelspace and MDI you need something like:

Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;
Transaction tr;

using(tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
{
if (!HostApplicationServices.WorkingDatabase.TileMode)
{
ObjectId objId = ed.CurrentViewportObjectId;
Autodesk.AutoCAD.DatabaseServices.Viewport vprt = (Autodesk.AutoCAD.DatabaseServices.Viewport)tr.GetObject(objId, OpenMode.ForRead);
dViewSize = vprt.Height;
}
else
{
ViewTableRecord vprtCur = ed.GetCurrentView();
dViewSize = vprtCur.Height;
}
}


The easiest thing would still be to just ask for "viewSize" variable:
double dViewSize = (double)Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("ViewSize");
Message 10 of 13
bobbydehero
in reply to: dubinskyv

I suppose you've found a solution by now, anyway... to monitor zoom events I think you need a combination of 'CommandEnded' reactor (for ZOOM command) and a windows message hook that monitors WM_WHEEL (rt zoom).
Message 11 of 13
PowerKiKi2
in reply to: dubinskyv

Your simplified solution is not correct. As I suggested in a previous post there is a problem when the area displayed to the end-user is not a square. That is almost always the case. That would usually be a wide rectangle. (I actually use this approximation as a temporary workaround)

But the code you provide may be the answer. I don't have time to try it now, but I assume vprt.Height and vprt.Width would be enough to know the get the real size displayed to the end-user.
Message 12 of 13
PowerKiKi2
in reply to: dubinskyv

What if the wheel function is assigned to another button/keys in AutoCAD configuration ? (Is it even possible to change that ?)
Message 13 of 13
bobbydehero
in reply to: dubinskyv

It works perfectly and good enough for me to determine whether a zoom has occured from a saved state, which was the original posted issue - a couple of years back 🙂
Hope you can make use of my sample code anyway.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost