Getting Screen coordinate from Revit coordinate.

Getting Screen coordinate from Revit coordinate.

tshunau
Contributor Contributor
1,961 Views
1 Reply
Message 1 of 2

Getting Screen coordinate from Revit coordinate.

tshunau
Contributor
Contributor

I was able to get the screen coordinate from Revit coordinate from the post when the user is working in the view. 

http://thebuildingcoder.typepad.com/blog/2012/06/uiview-and-windows-device-coordinates.html.

However, I notice that there's a problem (the screen coordinate is not accurate)  when the user working in a view that is located on the sheet via (activate view).  Is there a way to overcome this problem? 

 

Tak Au,

1,962 Views
1 Reply
Reply (1)
Message 2 of 2

FAIR59
Advisor
Advisor

The code from thebuildingcoder finds the first UIView it encounters. That window (view) need not be the one representing the Document.ActiveView.

 

It is possible to have more than 1 window showing the same view,

  • your situation, activated viewport on sheet and the same view also open.
  • a second instance of a view opened with [View][Replicate Window]

For inactive views the window reverts to the size and position of "Cascade Windows", which explains the unexpected values for uiview.GetWindowRectangle() and uiview.GetZoomCorners().

 

InActiveViewRectangle.PNG

Using Automation you can find the ClientRectangle of the active window displaying the active view. This Rectangle will be the criterium to select the active one from all the uiviews with uiview.ViewId == doc.ActiveView.Id.

 

Here's the code (code written for macro).

			View activeView = doc.ActiveView;
			List<UIView> uiViewsWithActiveView = new List<UIView>();
			foreach (UIView  uiv in this.ActiveUIDocument.GetOpenUIViews())
			{
				if (uiv.ViewId.IntegerValue == activeView.Id.IntegerValue) uiViewsWithActiveView.Add(uiv);
			}
			
			UIView ActiveUIView = uiViewsWithActiveView.FirstOrDefault();
			if (uiViewsWithActiveView.Count>1)
			{
// 2 or more windows showing the same view
// use Automation to find the active window
				IntPtr revitHandle  = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
				AutomationElement root = AutomationElement.FromHandle(revitHandle);
// find the container control for the open views   				
				PropertyCondition workSpaceCondition
		        	= new PropertyCondition(
        			  AutomationElement.ClassNameProperty,
        			  "MDIClient");
				AutomationElement workspace = root.FindFirst(TreeScope.Descendants,workSpaceCondition);
//find the active window in the workspace == first childwindow
				AutomationElement firstviewWindow = workspace.FindFirst(TreeScope.Children,Condition.TrueCondition);
				PropertyCondition classCondition
		      	  = new PropertyCondition(
        			  AutomationElement.ClassNameProperty,
        			  "AfxFrameOrView110u");
//get clientrectangle
				AutomationElement viewPane = firstviewWindow.FindFirst(TreeScope.Children,classCondition);
				System.Windows.Rect boundingRect1;
				object boundingRectNoDefault =
    			viewPane.GetCurrentPropertyValue(AutomationElement.BoundingRectangleProperty, true);

//select uiview with identical clientrectangle
				boundingRect1 = (System.Windows.Rect)boundingRectNoDefault;
 				foreach(UIView uiv in uiViewsWithActiveView)
 				{
 					Rectangle r1 = uiv.GetWindowRectangle();
 					if( r1.Left == boundingRect1.Left && r1.Top==boundingRect1.Top
 					   && r1.Right == boundingRect1.Right && r1.Bottom == boundingRect1.Bottom)
 					{
 						ActiveUIView = uiv;
 						break;
 					}
 				}
			}
			if (ActiveUIView==null) return;


  			Rectangle rect = ActiveUIView.GetWindowRectangle();
  			IList<XYZ> corners = ActiveUIView.GetZoomCorners();
  			XYZ p = corners[0];
  			XYZ q = corners[1];
 
  			string msg = string.Format( 
    			"UIView Windows rectangle: {0}; "
    			+ "zoom corners: {1}-{2}; ", 
    				RectangleString( rect ), 
    				 p ,  q  );
  			TaskDialog.Show("coordinates",msg);