Wednesday, September 05, 2007
Posted on Wednesday, September 05, 2007 2:34:42 AM (Mountain Daylight Time, UTC-06:00)  Comments [1] | 
Categories: .NET | ArcGIS Devt | ArcMap

While I was at home, away from my source tree at work, I was looking to correctly parent a form to ArcMap. By parenting a form to ArcMap, it will be minimized with ArcMap, and will always stay in front of ArcMap - important if you want to have multiple forms up at the same time, and what them all to be visible!

In the past we've always used the Win32 API 's SetWindowLong function - which we wrapped up a little in a helper class. Not having the source to look at, or the helper class to use, I needed to figure out the syntax. To complicate things, I was also writing the code in C# - it's those subtle changes that will always mess you up. After finding the PInvoke site, and locating the SetWindowLong function there, and being somewhat confused about how to get an IntPtr from Application.hWnd, I did a search in the ESRI forums. Low and behold I found this recent post (July 31, 2007) by Berend Veldkamp in which he provides a very simple way to parent a form to ArcMap.

In .Net 2.0 it's possible to pass a parent window to the Show method of your form. This should be an object implementing IWin32Window, here's a basic example of how to do that in VB.Net 

Doh! Amazing what you overlook because you're used to doing things the old way - I had no idea that Form.Show had a parent option. Anyhow, I'll let you get the VB.NET version from the forum post - here's the C# version: 

 public class ArcMapWindow : System.Windows.Forms.IWin32Window

 {

    private IApplication m_app;

 

    public ArcMapWindow(IApplication application)

    {

        m_app = application;

    }

 

    public System.IntPtr Handle {

        get { return new IntPtr(m_app.hWnd); }

    }

 

 }

Now, to show a form parented to ArcMap, all I need to do is...

form.Show(new ArcMapWindow(m_application));

This is much simpler and avoids the Win32 API call. Thanks Berend!

Wednesday, September 05, 2007 8:40:15 AM (Mountain Daylight Time, UTC-06:00)
This is just a subtle difference, but I think it is preferable since it eliminates the extra Application reference being stored in the window class.

public class WindowWrapper : System.Windows.Forms.IWin32Window
{
private IntPtr _hwnd;
public WindowWrapper(int handle)
{
_hwnd = (IntPtr)handle;
}
public IntPtr Handle
{
get { return _hwnd; }
}
}


And then call with:
Form.Show(new WindowWrapper(m_Application.hWnd));

Like I said, minor change.
Jeff Machamer
Comments are closed.