Створення плаваючого (не стикуваного) вікна в ArcMap за допомогою ArcObjects?


9

Я шукаю спосіб створити плаваюче вікно в ArcMap. Для прикладу просто подивіться у вікно інструменту «Ідентифікувати».

Плаваючий означає, що він весь час залишається перед картою документа і користувач може продовжувати працювати з ArcMap. Я знаю, що інтерфейс IDockableWindowDef можна використовувати для створення стикувальних вікон, які також можуть плавати, але я не хочу, щоб вони стикувалися . Наскільки мені відомо, не можна запобігти стикуванню форм, створених IDockableWindowManager, якщо, наприклад, користувач натискає їх до межі вікна ArcMap.

Будь-які ідеї?


Рішення полягало в пошуку таких ключових слів, як дочірнє вікно та MDI. HTH

Здається, вирішення проблеми настільки ж просто, як і відповідь @ llcf :

MyForm form = new MyForm();
form.Show(NativeWindow.FromHandle(new IntPtr(m_application.hWnd)));

Мені подобається такий спосіб NativeWindow - дуже чистий.
Відар

Відповіді:


7

Якщо в .net, я думаю, що приклади, які я бачив, використовують хелперний клас, як показано нижче:

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;
  }

Так! Замість вашої обгортки я використав NativeWindow.FromHandle (), який робить точно так само. На мою думку, це працює і виглядає елегантніше, ніж рішення з user32.dll. Дякую.
AndOne

3

Я знайшов відповідь на цю проблему за допомогою старих форумів ESRI. Щойно раніше використовували неправильні ключові слова: / Рішення лежить у 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);
    }
}

Я не зовсім впевнений, чи 64-бітова сумісність реалізована правильно, оскільки SetWindowLongPtr () повинен замінити SetWindowLong (), але мені не вдалося змусити її працювати на моїй 64-бітній машині. Завжди отримував EntryPointNotFoundException. Але, принаймні, це працює з моїми налаштуваннями розробників.


0

Якщо ви використовуєте .NET, найкраща ставка - створити режим без форм Windows і встановити властивість TopMost на true. Ви також захочете встановити властивість Parent Form для програми ArcMap.

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
Дякую, але, на жаль, це не так, як потрібно. Істинність TopMost форма залишається перед усіма іншими вікнами, навіть коли ArcMap зведений до мінімуму. Якщо встановлено значення false, форма буде прихована за вікном ArcMap.
AndOne
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.