Czy tworzysz okno pływające (nie dokowalne) w ArcMap za pomocą ArcObjects?


9

Szukam sposobu na utworzenie pływającego okna w ArcMap. Aby podać przykład, wystarczy spojrzeć na okno narzędzia Identyfikuj.

Pływający oznacza, że ​​pozostaje on zawsze przed dokumentem mapy i że użytkownik może kontynuować pracę z ArcMap. Wiem, że interfejsu IDockableWindowDef można używać do tworzenia dokowalnych okien, które również mogą się unosić, ale nie chcę, aby były dokowane . Według mojej wiedzy nie jest możliwe zapobieganie zadokowaniu formularzy utworzonych przez IDockableWindowManager, jeśli np. Użytkownik popchnie je do granicy okna ArcMap.

Jakieś pomysły?


Rozwiązaniem było wyszukiwanie słów kluczowych, takich jak okno potomne i MDI. HTH

Rozwiązanie problemu wydaje się tak proste, jak odpowiedź @ llcf :

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

Podoba mi się ten sposób NativeWindow - bardzo czysty.
Vidar

Odpowiedzi:


7

Jeśli w .net myślę, że przykłady, które widziałem, wykorzystują klasę pomocnika, jak poniżej:

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

Tak! Zamiast twojego opakowania użyłem NativeWindow.FromHandle (), który robi dokładnie to samo. Moim zdaniem działa i wydaje się bardziej elegancki niż rozwiązanie z user32.dll. Dzięki.
AndOne

3

Znalazłem odpowiedź na ten problem przy pomocy starszych forów ESRI. Do tej pory użyłem niewłaściwych słów kluczowych: / Rozwiązanie leży w 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);
    }
}

Nie jestem pewien, czy zgodność 64-bitowa została zaimplementowana poprawnie, ponieważ SetWindowLongPtr () ma zastąpić SetWindowLong (), ale nie byłem w stanie zmusić go do działania na moim komputerze 64-bitowym. Zawsze otrzymywał wyjątek EntryPointNotFoundException. Ale przynajmniej działa to z moją konfiguracją programistów.


0

Jeśli używasz platformy .NET, najlepszym rozwiązaniem jest utworzenie niemodalnego formularza Windows i ustawienie właściwości TopMost na wartość true. Będziesz także chciał ustawić właściwość Parent formularza w aplikacji 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
Dzięki, ale niestety nie zachowuje się tak, jak prosiliśmy. Ponieważ TopMost jest prawdziwy, forma pozostaje przed wszystkimi innymi oknami, nawet gdy ArcMap jest zminimalizowany. Jeśli zostanie ustawiona wartość false, formularz zostanie ukryty za oknem ArcMap.
AndOne
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.