8

I'm looking for a way to create a floating window in ArcMap. To give an example just look at the window of the Identify tool.

Floating means that it stays in front of the map document at all times and that the user can continue to work with ArcMap. I know that the interface IDockableWindowDef can be used to create dockable windows which can also float, but I don't want them to dock. To my knowledge it's not possible to prevent forms created by IDockableWindowManager from docking if e.g. the user pushes them to the border of the ArcMap window.

Any ideas?


The solution was to search for keywords like child window and MDI. HTH

The problem's solution seems to be as easy as @llcf's answer:

MyForm form = new MyForm();
form.Show(NativeWindow.FromHandle(new IntPtr(m_application.hWnd)));
  • I like this NativeWindow way - very clean. – Vidar Mar 2 '12 at 8:07
7

If in .net I think the examples I have seen uses a helper class as below:

var form = new Form1();
form.Show(new WindowWrapper(_mxDocument.ActiveView.ScreenDisplay.hWnd));

public class WindowWrapper : System.Windows.Forms.IWin32Window
  {
    public WindowWrapper(IntPtr handle)
    {
      m_hwnd = handle;
    }
    public WindowWrapper(int handle)
    {
      m_hwnd = (IntPtr)handle;
    }
    public IntPtr Handle
    {
      get
      {
        return m_hwnd;
      }
    }
    private IntPtr m_hwnd;
  }
  • Yes! Instead of your wrapper I used NativeWindow.FromHandle() which does exactly the same. It works and seems more elegant than the solution with user32.dll, in my view. Thanks. – AndOne Oct 22 '10 at 16:20
3

I found the answer to this problem with the help of the older ESRI forums. Just had used the wrong keywords until now :/ The solution lies in SetWindowLong():

// import external methods
[DllImport("user32.dll")]
static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll")]
static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
private int GWL_HWNDPARENT = -8;

public TestForm()
{
    InitializeComponent();

    IntPtr mxPtr = new IntPtr(GetApplicationReference().hWnd);
    if(IntPtr.Size == 8) { // needed for 64bit compatibility?
        SetWindowLongPtr(this.Handle, GWL_HWNDPARENT, mxPtr);
    } else {
        SetWindowLong(this.Handle, GWL_HWNDPARENT, mxPtr);
    }
}

I'm not quite sure if the 64bit compatibility is implemented right because SetWindowLongPtr() is supposed to supersed SetWindowLong() but I wasn't able to get it to work on my 64bit machine. Always got an EntryPointNotFoundException. But at least this works with my dev setup.

0

If you're using .NET, creating a modeless Windows Form and setting the TopMost property to true is the best bet. You'll also want to set the Form's Parent property to the ArcMap application.

sealed class MyForm : Form
{
    // ... other impl ...

    public void SetMxParent(IApplication app)
    {
        IntPtr mxPtr = new IntPtr(app.hWnd);
        this.Parent = Control.FromHandle(mxPtr);

        // optionally
        this.TopMost = true;
    }
}
  • 1
    Thanks, but unfortunately this doesn't behave like requested. With TopMost being true the form stays in front of all other windows even when ArcMap is minimized. If it is set to false, the form will be hidden behind the ArcMap window. – AndOne Oct 22 '10 at 12:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.