tags:

views:

106

answers:

3

Hi there,

i get a winHdl (which is a winForm) from a native c++ application.

Plugin implementation in c#:

public int Create(int hParentWnd ...){ ... // here i want to put wpf on this hParentWnd }

Now i want to put my WPF user control in this window. How can i do this? Any code snippets available?

thanks

A: 

ElementHost is what you are looking for, it's a WinForms control that hosts WPF content.

http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.elementhost.aspx

Nir
Thank you for your awnser..Anyway i have to create a Form out of the WinHandle and then i have to import the wpf into the Form. I heard about a more straight way to paint WPF on WinHandles. Your suggestion is just a workaround for me.
elCapitano
A: 

You don't need WinForms to do this. You can use HwndSource directly:

  public void CreateControl(IntPtr hParentWnd)
  {
    _userControl = new MyWPFUserControl();

    var parameters = 
      new HwndSourceParameters("", _initialWidth, _initialHeight)
      {
        ParentWindow = (IntPtr)hwndParent,
        WindowStyle = ...,          // Win32 style bits
        ExtendedWindowStyle = ...,  // Win32 ex style bits
      })

    _hwndSource = 
      new HwndSource(parameters) { RootVisual = _userControl };
  }

  public void DestroyControl()
  {
    _hwndSource.Destroy();
  }

The parameter to CreateControl really ought to be IntPtr, not 'int', but you can set it to 'int' if you need to and just cast it to IntPtr later on.

If you want to return the handle of the newly created window, return _hwndSource.Handle.

Ray Burns
This is exactly what i was searching for!!! Thank you very much!
elCapitano
either the cast from int to intPtr did not work or something else is wrong: the parent control is set correctly (when i change the tab my WPF window disapears correctly), but it is not painted directly on the c++ tab. can i get the parent window to set the docking to dock-style full??
elCapitano
In native Windows applications, the size and position of a child hWnd is generally controlled by the parent hWnd. Unless you specifically set SizeToContent or AdjustSizingForNonClientArea in your WPF code, HwndSource will just use GetClientRect(hWndChild). If you can modify the parent's code, just change it so it does SetClientRect(hWndChild, ...) on each WM_SIZE. If not, you can still subclass the parent window's WndProc to trap WM_SIZE, but this is more work.
Ray Burns
A: 

Ok, i figured it out. Here is the result:

                int WS_CHILD = 0x40000000;
                int WS_VISIBLE = 0x10000000;

                // paint wpf on int hParentWnd
                myWindow = new MyWpfWindow();

                // First it creates an HwndSource, whose parameters are similar to CreateWindow:
                HwndSource otxHwndSource = new HwndSource(
                                        0,                          // class style
                                        WS_VISIBLE | WS_CHILD,      // style
                                        0,                          // exstyle
                                        10, 10, 200, 400,
                                        "MyWpfWindow",             // NAME
                                        (IntPtr)hParentWnd          // parent window
                                        );

                otxHwndSource.RootVisual = ...;

                // following must be set to prcess key events
                myHwndSource.AddHook(new HwndSourceHook(ChildHwndSourceHook));

with the hook:

private IntPtr ChildHwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == (int)(0x0087)) //WM_GETDLGCODE
            {
                handled = true;
                int returnCode = (int)(0x0080);
                return new IntPtr(returnCode);
            }
            return System.IntPtr.Zero;
        }

thanks to Ray Burns!

elCapitano