none
Setting a Window as the Owner of a Form? RRS feed

  • Question

  • Can I somehow set a Wpf Window as the owner of a Winforms Form?
    I've seen this article which describes the other way round.

    I searched a bit and thought I might be able to set the owner of the winforms form by using the handle from the Wpf Window but I can't find any p/invoke calls that would do that?

    Code Block

    System.Windows.Forms.Form form = new System.Windows.Forms.Form();
                   
    System.Windows.Interop.WindowInteropHelper hlp = new System.Windows.Interop.WindowInteropHelper(this);

    //SetOwner(form, hlp.Handle); ???



    Any ideas?
    Wednesday, October 31, 2007 5:14 AM

Answers

  • Hi Patrick,

     

         If you want to set a WPF Window as the owner of a Winform Form, you need to use a bit of pinvoke code:

     

    Code Block

    public partial class Window1 : Window

    {

        [DllImport("user32.dll")]

        private static extern int SetWindowLong(HandleRef hWnd, int nIndex, int dwNewLong);

        public Window1()

        {

            InitializeComponent();

            btn.Click += delegate

            {

                Form frm = new Form();

                frm.Width = 300;

                frm.Height = 200;

                frm.StartPosition = FormStartPosition.CenterParent;

                WindowInteropHelper helper = new WindowInteropHelper(this);

                SetWindowLong(new HandleRef(frm, frm.Handle), -8, helper.Handle.ToInt32());

                frm.Show();

            };

        }

    }

     

     

        Hope this helps
    Friday, November 2, 2007 5:57 AM
  • I got the information from MSDN that:

    "You must not call SetWindowLong with the GWL_HWNDPARENT index to change the parent of a child window. Instead, use the SetParent function."

    (see http://msdn2.microsoft.com/en-us/library/ms633591.aspx)

    So the following method is the right way. I tried it, It works.

     

    [DllImport("user32.dll")]
    public extern static int SetParent(int child, int parent);

     

    WindowInteropHelper helper = new WindowInteropHelper(parWPFWindow);
    SetParent(childForm.Handle.ToInt32(), helper.Handle.ToInt32());

     

    See:  http://msdn2.microsoft.com/en-us/library/ms633541.aspx

    Wednesday, December 5, 2007 9:22 AM

All replies

  • I stumbled upon an interesting article while researching. This article describes how to host a Winforms Form in Wpf much like the WindowsFormsHost for Controls...
    Wednesday, October 31, 2007 5:49 AM
  • Hi Patrick,

     

         If you want to set a WPF Window as the owner of a Winform Form, you need to use a bit of pinvoke code:

     

    Code Block

    public partial class Window1 : Window

    {

        [DllImport("user32.dll")]

        private static extern int SetWindowLong(HandleRef hWnd, int nIndex, int dwNewLong);

        public Window1()

        {

            InitializeComponent();

            btn.Click += delegate

            {

                Form frm = new Form();

                frm.Width = 300;

                frm.Height = 200;

                frm.StartPosition = FormStartPosition.CenterParent;

                WindowInteropHelper helper = new WindowInteropHelper(this);

                SetWindowLong(new HandleRef(frm, frm.Handle), -8, helper.Handle.ToInt32());

                frm.Show();

            };

        }

    }

     

     

        Hope this helps
    Friday, November 2, 2007 5:57 AM
  • Thanks Marco!
    Friday, November 2, 2007 6:01 AM
  • I got the information from MSDN that:

    "You must not call SetWindowLong with the GWL_HWNDPARENT index to change the parent of a child window. Instead, use the SetParent function."

    (see http://msdn2.microsoft.com/en-us/library/ms633591.aspx)

    So the following method is the right way. I tried it, It works.

     

    [DllImport("user32.dll")]
    public extern static int SetParent(int child, int parent);

     

    WindowInteropHelper helper = new WindowInteropHelper(parWPFWindow);
    SetParent(childForm.Handle.ToInt32(), helper.Handle.ToInt32());

     

    See:  http://msdn2.microsoft.com/en-us/library/ms633541.aspx

    Wednesday, December 5, 2007 9:22 AM
  • thanks for the additional information kingbird. Just as a side note: I wasn't trying to change the parent but just set it, so SetWindowLong should be fine as well but SetParent seems more logical anyway...
    Wednesday, December 5, 2007 9:31 AM
  • Be aware that the technique Marco is showing is undocumented. A future version of Windows might break it. It's unfortunate, but there is no SetOwner() function in Win32. What's officially supported is setting a window's owner at creation time. If that would suffice for your purpose, then you can do it more cleanly:

          NativeWindow ownerWindow = new NativeWindow();

          ownerWindow.AssignHandle((new WindowInteropHelper(wpfWindow)).Handle);

          form.Show(ownerWindow);

     

    Friday, December 7, 2007 9:46 PM
  • Ok, I have a similar problem:

    I've got two windows, each on the opposite side of an AppDomain. The window that is supposed to be the child window knows about the handle of the parent window. Both of these are WPF windows.

    I need to set the owner of the child window at some point, be it creation or after the fact.

    I was using interop helper like so:
    WindowInteropHelper helper = new WindowInteropHelper(m_wind);
    helper.Owner = m_properties.OwnerHandle;

    But i ran into a VERY strange issue where, if my window is maximized (it's a window with WindowStyle="None" and ResizeMode="NoResize"), the parent steals activation from the child after a few seconds. This only happens when it is maximized. Taking out the interop helper fixes the active window stealing, but breaks the fact that it is a child window.

    SetWindowLong methodology for setting the ownership has the same problem.

    I tried to use the SetParent API call as well. This got rid of my problem with the owner stealing focus from the child. It also took over positioning of the window for me. Unfortunately, I do still need to change the positioning and size of that child window. When I do, the resizing and repositioning of the window happens, but the content of my window suddeny thinks that it has the same dimensions of the parent window. Say my child has 300x700. This shows as 300x700, but inside my child window, its ActualHeight and ActualWidth will read as 1024x768. In fact, the Resize event of the child window sees the sizing as 1024x768 and doesn't want it any other way.

    Any clue as to what's going on here?

    Is there any other way that i could host a WPF window, knowing only the handle, inside another WPF window?
    Wednesday, December 12, 2007 9:41 PM
  • Kayakyakr,

    First, let me state that multi-AppDomain support in WPF is officially supported only with add-ins, which requires .NET 3.5. We know other setups mostly work as well, but we haven't yet done the exhaustive testing needed to declare them supported. The focus glitch you are seeing may well be an outstanding bug in this area.

    Second, it is not clear to me whether you want to set up a parent or owner relationship between the two windows [MSDN doc]. Either way, to try to narrow down the possible causes, first find out what Win32 window styles are applied to both windows involved. The Spy++ tool can show you this. We have a known bug with WS_POPUP applied to an owned window that causes focusing anomalies.

    It may be easiest to get help from someone if you post a minimal repro application.

     

     

    - - -

    Want to change the way Windows and Internet GUI applications are created? The WPF AppModel team is hiring!

    - - -

     

    Thursday, December 13, 2007 7:05 PM
  •  Chango V. - MSFT wrote:

    Kayakyakr,

    First, let me state that multi-AppDomain support in WPF is officially supported only with add-ins, which requires .NET 3.5. We know other setups mostly work as well, but we haven't yet done the exhaustive testing needed to declare them supported. The focus glitch you are seeing may well be an outstanding bug in this area.

    Second, it is not clear to me whether you want to set up a parent or owner relationship between the two windows [MSDN doc]. Either way, to try to narrow down the possible causes, first find out what Win32 window styles are applied to both windows involved. The Spy++ tool can show you this. We have a known bug with WS_POPUP applied to an owned window that causes focusing anomalies.

    It may be easiest to get help from someone if you post a minimal repro application.

     

     

    - - -

    Want to change the way Windows and Internet GUI applications are created? The WPF AppModel team is hiring!

    - - -

     



    With some testing and messing, I believe that I have found a combination of window styles and ownership that allows me to have this setup without experiencing the focusing issues. As a side effect, I implemented code that forced a style-less window to honor the task bar when maximized instead of running as full screen. And to be clear, I had attempted to set up both ownership and parenthood as different potential solutions.

    We approached the use of appdomains knowing that it wasn't officially supported in .net 3.0. We haven't officially moved over to .Net 3.5 yet, so I haven't yet been able to assess what it will take to move to a supported model using add-ins. The current design allows us to easily support interop with delphi processes, though, and we're not likely to be able to get rid of these delphi apps for some time.
    Monday, December 17, 2007 8:20 PM