Get Position of Page Layout

996
4
Jump to solution
06-08-2017 04:50 PM
RiverTaig2
New Contributor II

I'm trying to get the pixel location of where the upper left corner of the ArcMap application is and more importantly the location of data frame on the page layout.  How can I do that in ArcObjects?  If, for example, ArcMap's upper left corner is slightly away from the screen's upper left corner, how do I get that offset and where does the data frame start (in pixel space relative to the screen's 0,0 position) ?   IActiveView:Extent.XMin seems tells you how far the PageLayout is from the left edge of its container, but I don't know how far that container is from the left edge of ArcMap or how far ArcMap is from the left edge of the screen.

0 Kudos
1 Solution

Accepted Solutions
RiverTaig2
New Contributor II

I've got it solved (to my satisfaction) with the code below.  To summarize the goal was essentially to take a screen capture of the data frame (map) when in page layout view. There's some additional code (not shown) which then puts the dataframe into "draft mode" and then plops the screenshot as an IPictureElement on top of the data frame.  This methodology essentially "freezes" the data frame so that when people are panning/zooming in page layout mode, they don't have to wait for the screen to redraw at all, but they can still see their map (albeit pixelated when they zoom in).  There's more code (not shown) which removes the screen capture image and puts it back into regular "live" update mode. 


/// <summary>
/// This method is called first (before Get Position Paramaters) to return a couple of objects needed to determine the area to export
/// </summary>
/// <param name="myRect"></param>
/// <param name="mdt"></param>
private static void GetWindowsRectangleAndDisplayTransformation(out User32.Rect windowRect, out IDisplayTransformation mdt)
{
IMap map = ArcMap.Document.FocusMap;
IActiveView mav = map as IActiveView;
IScreenDisplay sd = mav.ScreenDisplay;
var winHandle = ((IScreenDisplay2)sd).hWnd;
IntPtr winHandlePoint = new IntPtr(winHandle);
windowRect = new User32.Rect();
User32.GetWindowRect(winHandlePoint, ref windowRect);
mdt = mav.ScreenDisplay.DisplayTransformation; //Map Display Transformation
}

/// <summary>
/// Returns the width and height of the area to export (deltaX,deltaY) and the rect which defines the pixel area to export (0,0 is top left of screen)
/// </summary>
/// <param name="mxDoc">IMxDocument</param>
/// <param name="myRect">pixel area to export</param>
/// <param name="mdt">map display transformeation</param>
/// <param name="el">The element which contains the dataframe</param>
/// <param name="fm">Map Frame (same as el but case to map frame)</param>
/// <param name="deltaX">output width to export</param>
/// <param name="deltaY">output height to export</param>
/// <param name="rect">The recangle which defines the area to take a screen capture of</param>
/// <returns></returns>
private static User32.Rect GetPositionParameters(IMxDocument mxDoc, User32.Rect windowRect, IDisplayTransformation mdt, IElement el, IMapFrame fm, out int deltaX, out int deltaY, out User32.Rect rect)
{
int xMin = 0; int yMin = 0; int xMax = 0; int yMax = 0;
mdt.FromMapPoint(fm.MapBounds.UpperLeft, out xMin, out yMin);
mdt.FromMapPoint(fm.MapBounds.LowerRight, out xMax, out yMax);
deltaX = xMax - xMin;//width in pixels to export
deltaY = yMax - yMin;//Height in pixels to export
double elXMin = el.Geometry.Envelope.XMin;
var screenPoint = GetCursorPosition();
int startX = 0;// screenPoint.X - mxDoc.CurrentLocation.X;
int startY = 0;// screenPoint.Y - mxDoc.CurrentLocation.Y;
mdt.FromMapPoint(mxDoc.CurrentLocation, out startX, out startY);
startX = xMin + windowRect.left;
startY = yMin + windowRect.top;
rect = new User32.Rect();
rect.top = startY;
rect.left = startX;
rect.right = deltaX - startX;
rect.bottom = deltaY - startY;
return windowRect;
}


/// <summary>
/// Returns the file name of the bitmap which is saved to disk
/// </summary>
/// <param name="deltaX"></param>
/// <param name="deltaY"></param>
/// <param name="rect"></param>
/// <returns></returns>
private string CreateScreenCaptureOfDataFrame(int deltaX, int deltaY, ref User32.Rect rect)
{
var bmp = new Bitmap(deltaX, deltaY, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bmp);
graphics.CopyFromScreen(rect.left, rect.top, 0, 0, new Size(deltaX, deltaY), CopyPixelOperation.SourceCopy);
string fileName = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Freeze.png";
bmp.Save(fileName, ImageFormat.Png);
return fileName;
}

[DllImport("user32.dll")]
public static extern bool GetCursorPos(out POINT lpPoint);
public static System.Drawing.Point GetCursorPosition()
{
POINT lpPoint;
GetCursorPos(out lpPoint);
return lpPoint;
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref User32.Rect rect);
public class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
}

View solution in original post

0 Kudos
4 Replies
DuncanHornby
MVP Notable Contributor

This sounds like a question more suited for stack exchange as the position of the window relative to the screen display is more of an operating system "thing", found this thread, this should help?

RiverTaig2
New Contributor II

You are partly right for sure - I can probably use the technique suggested in the stack overflow thread to get the ArcMap application position. But I'll still need to find the page layout using ArcObjects i think

0 Kudos
KenBuja
MVP Esteemed Contributor

The window's position is stored in the registry's Current User (HKEY_CURRENT_USER). You can use .Net's Registry.CurrentUser to get this.

For example, this was how I got information about the ArcGIS license from the registry (this was in a 9.x version, though)

regVersion = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\\ESRI\\License", False)
If regVersion.GetValue("SEAT_PREFERENCE", "") <> "Float" Then
  Return False
  Exit Function
End If
RiverTaig2
New Contributor II

I've got it solved (to my satisfaction) with the code below.  To summarize the goal was essentially to take a screen capture of the data frame (map) when in page layout view. There's some additional code (not shown) which then puts the dataframe into "draft mode" and then plops the screenshot as an IPictureElement on top of the data frame.  This methodology essentially "freezes" the data frame so that when people are panning/zooming in page layout mode, they don't have to wait for the screen to redraw at all, but they can still see their map (albeit pixelated when they zoom in).  There's more code (not shown) which removes the screen capture image and puts it back into regular "live" update mode. 


/// <summary>
/// This method is called first (before Get Position Paramaters) to return a couple of objects needed to determine the area to export
/// </summary>
/// <param name="myRect"></param>
/// <param name="mdt"></param>
private static void GetWindowsRectangleAndDisplayTransformation(out User32.Rect windowRect, out IDisplayTransformation mdt)
{
IMap map = ArcMap.Document.FocusMap;
IActiveView mav = map as IActiveView;
IScreenDisplay sd = mav.ScreenDisplay;
var winHandle = ((IScreenDisplay2)sd).hWnd;
IntPtr winHandlePoint = new IntPtr(winHandle);
windowRect = new User32.Rect();
User32.GetWindowRect(winHandlePoint, ref windowRect);
mdt = mav.ScreenDisplay.DisplayTransformation; //Map Display Transformation
}

/// <summary>
/// Returns the width and height of the area to export (deltaX,deltaY) and the rect which defines the pixel area to export (0,0 is top left of screen)
/// </summary>
/// <param name="mxDoc">IMxDocument</param>
/// <param name="myRect">pixel area to export</param>
/// <param name="mdt">map display transformeation</param>
/// <param name="el">The element which contains the dataframe</param>
/// <param name="fm">Map Frame (same as el but case to map frame)</param>
/// <param name="deltaX">output width to export</param>
/// <param name="deltaY">output height to export</param>
/// <param name="rect">The recangle which defines the area to take a screen capture of</param>
/// <returns></returns>
private static User32.Rect GetPositionParameters(IMxDocument mxDoc, User32.Rect windowRect, IDisplayTransformation mdt, IElement el, IMapFrame fm, out int deltaX, out int deltaY, out User32.Rect rect)
{
int xMin = 0; int yMin = 0; int xMax = 0; int yMax = 0;
mdt.FromMapPoint(fm.MapBounds.UpperLeft, out xMin, out yMin);
mdt.FromMapPoint(fm.MapBounds.LowerRight, out xMax, out yMax);
deltaX = xMax - xMin;//width in pixels to export
deltaY = yMax - yMin;//Height in pixels to export
double elXMin = el.Geometry.Envelope.XMin;
var screenPoint = GetCursorPosition();
int startX = 0;// screenPoint.X - mxDoc.CurrentLocation.X;
int startY = 0;// screenPoint.Y - mxDoc.CurrentLocation.Y;
mdt.FromMapPoint(mxDoc.CurrentLocation, out startX, out startY);
startX = xMin + windowRect.left;
startY = yMin + windowRect.top;
rect = new User32.Rect();
rect.top = startY;
rect.left = startX;
rect.right = deltaX - startX;
rect.bottom = deltaY - startY;
return windowRect;
}


/// <summary>
/// Returns the file name of the bitmap which is saved to disk
/// </summary>
/// <param name="deltaX"></param>
/// <param name="deltaY"></param>
/// <param name="rect"></param>
/// <returns></returns>
private string CreateScreenCaptureOfDataFrame(int deltaX, int deltaY, ref User32.Rect rect)
{
var bmp = new Bitmap(deltaX, deltaY, PixelFormat.Format32bppArgb);
Graphics graphics = Graphics.FromImage(bmp);
graphics.CopyFromScreen(rect.left, rect.top, 0, 0, new Size(deltaX, deltaY), CopyPixelOperation.SourceCopy);
string fileName = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\Freeze.png";
bmp.Save(fileName, ImageFormat.Png);
return fileName;
}

[DllImport("user32.dll")]
public static extern bool GetCursorPos(out POINT lpPoint);
public static System.Drawing.Point GetCursorPosition()
{
POINT lpPoint;
GetCursorPos(out lpPoint);
return lpPoint;
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref User32.Rect rect);
public class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct Rect
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
}

0 Kudos