Question

Using a class derived from HwndHost and some voodoo code:

protected override HandleRef BuildWindowCore(HandleRef hwndHost)
{
  CheckGuestValidity();
  var guestHwnd = new HandleRef(GuestHwnd, _guestHwnd);
  Win32.SetWindowStyle(guestHwnd.Handle, WindowStyles.WS_CHILD | Win32.GetWindowStyle(guestHwnd.Handle));
  WindowsFormsHost.EnableWindowsFormsInterop();
  System.Windows.Forms.Application.EnableVisualStyles();
  Win32.SetParent(guestHwnd.Handle, hwndHost.Handle);
  Win32.SetWindowStyle(_guestHwnd, Win32.GetWindowStyle(_guestHwnd) & ~WindowStyles.WS_CAPTION);
  return guestHwnd;
}

I have managed to get an otherwise parentless (except for Windows' main window) window from a Delphi COM server to adopt my WPF application window as it's parent window. Problem is it is located under all the other user controls etc. at the very bottom of my WPF window. I would like to size and position it to fit inside a rectangle on a tab in a TabControl. How can I go about this? I realise it will take a few resize and position Win32 API calls and maybe even a few low level Windows messages, but I'm up for it.

Was it helpful?

Solution

First I found a handy little class to convert between coordinate systems. It is @Lu55's answer , not the accepted one, to the question How do I convert a WPF size to physical pixels?

Then, my WindowHostView XAML looks like this:

<Grid x:Name="WindowContainer" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Coral" >
  <delphi:Win32WindowHost x:Name="Host" />
</Grid>

The Win32WindowHost class is what contains the code included in my question.

Now I have a neat little routine inside WindowHostView to fit the guest window into the the host's boundarys.

private void PositionGuestWindow(IntPtr hWnd)
{
  var rect = WindowContainer.GetAbsoltutePlacement();
  var winLeft = Win32Calc.PointsToPixels(rect.Left, Win32Calc.Dimension.Width);
  var winTop = Win32Calc.PointsToPixels(rect.Top, Win32Calc.Dimension.Height);
  var winWidth = Win32Calc.PointsToPixels(rect.Width, Win32Calc.Dimension.Width);
  var winHeight = Win32Calc.PointsToPixels(this.ActualHeight - 20, Win32Calc.Dimension.Height);

  Win32Api.MoveWindow(Host.GuestHwnd, (int)winLeft, (int)winTop, (int)winWidth + 1, (int)winHeight, true);
}

And Win32Api.MoveWindow is plain old:

[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top