简体   繁体   English

如何在WPF应用程序的用户控件中放置Win32浮动窗口?

[英]How can I position a Win32 floating window inside a user control in my WPF application?

Using a class derived from HwndHost and some voodoo code: 使用派生自HwndHost的类和一些伏都HwndHost代码:

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. 我已经设法从Delphi COM服务器获得了一个其他的无父窗口(Windows主窗口除外),以采用我的WPF应用程序窗口作为父窗口。 Problem is it is located under all the other user controls etc. at the very bottom of my WPF window. 问题是它位于WPF窗口最底部的所有其他用户控件等下。 I would like to size and position it to fit inside a rectangle on a tab in a TabControl. 我想将其大小和位置设置为适合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. 我意识到这将需要一些调整大小和定位Win32 API调用的位置,甚至可能会包含一些低级别的Windows消息,但是我赞成。

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? 这是@ Lu55的答案,而不是公认的问题, 如何将WPF大小转换为物理像素?

Then, my WindowHostView XAML looks like this: 然后,我的WindowHostView XAML如下所示:

<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. Win32WindowHost类是包含在我的问题中的代码。

Now I have a neat little routine inside WindowHostView to fit the guest window into the the host's boundarys. 现在,我在WindowHostView有一个简洁的小例程,以使来宾窗口适合主机的边界。

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: Win32Api.MoveWindow很老了:

[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM