在 WindowsFormsHost 之上呈现 WPF 控件

发布于 2024-11-06 13:14:57 字数 242 浏览 1 评论 0原文

我知道默认的 WPF 行为是渲染 WPF 控件,然后在顶部渲染 WinForms,但是有没有办法在 WindowsFormsHost 之上渲染 WPF?

编辑:我也发现了一个临时黑客。当 wpf 控件重叠 WindowsFormsHost 时,我更改 WindowsFormsHost 的大小(这只适用于重叠的矩形对象,不适用于其他形状。)

I know that default WPF behavior is to render WPF controls and then on top render WinForms, but are there any way to render WPF on top of WindowsFormsHost?

Edit: I have found a temp hack as well. When wpf control overlaps WindowsFormsHost, I change the size of the WindowsFormsHost (This only works when you have rectangular object which overlaps, doesn't work for other shapes.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

墨落画卷 2024-11-13 13:14:57

我知道,迟到了,但我最近使用 WebBrowser 控件遇到了这个问题。

最终的修复是每当我在顶部托管模式对话框时就创建网络浏览器的屏幕截图。由于这有点繁琐,我将其变成了一个 Github 项目,希望这会有所帮助 -

https://github。 com/chris84948/AirspaceFixer

(它也在 Nuget 上,在 AirspaceFixer 下)

一旦你拥有了该项目,你需要做的就是这里

xmlns:asf="clr-namespace:AirspaceFixer;assembly=AirspaceFixer"

<asf:AirspacePanel FixAirspace="{Binding FixAirspace}">
    <WebBrowser x:Name="Browser" />
</asf:AirspacePanel>

FixAirspace是从内容的“真实”视图切换到屏幕截图或“假”视图的依赖属性。

Late to the party, I know, but I recently came across this issue using a WebBrowser control.

The final fix was to create a screenshot of the web browser whenever I hosted a modal dialog over the top. Since this was a little fiddly, I turned it into a Github project, hopefully this helps a little -

https://github.com/chris84948/AirspaceFixer

(It's on Nuget too, under AirspaceFixer)

Once you have the project all you need to do is this

xmlns:asf="clr-namespace:AirspaceFixer;assembly=AirspaceFixer"

<asf:AirspacePanel FixAirspace="{Binding FixAirspace}">
    <WebBrowser x:Name="Browser" />
</asf:AirspacePanel>

Where FixAirspace is the dependency property that switches from the "real" view of the content, to the screenshot or "fake" view.

仅此而已 2024-11-13 13:14:57

此“空域”问题应该已修复< /a> 在 WPF vNext 中。有几个解决方案,例如 此处此处 和 这里

实现此目的的一种方法是将 WPF 内容托管在透明的弹出窗口或窗口中,该窗口覆盖互操作内容。

This "airspace" issue is suppose to be fixed in WPF vNext. There are a couple solutions out there, such as here, here, and here.

One way to do this is to host the WPF content in a transparent Popup or Window, which overlays the Interop content.

下壹個目標 2024-11-13 13:14:57

试穿一下尺码:

<hacks:AirspaceOverlay>
    <hacks:AirspaceOverlay.OverlayChild>
        <Canvas ToolTip = "A tooltip over a DirectX surface" Background="#01000000" Name="Overlay" />
    </hacks:AirspaceOverlay.OverlayChild>
    <controls:OpenGLControlWrappingWindowsFormsHost />
</hacks:AirspaceOverlay>


// Adapted from http://blogs.msdn.com/b/pantal/archive/2007/07/31/managed-directx-interop-with-wpf-part-2.aspx & http://www.4mghc.com/topics/69774/1/in-wpf-how-can-you-draw-a-line-over-a-windowsformshost
public class AirspaceOverlay : Decorator
{
    private readonly Window _transparentInputWindow;
    private Window _parentWindow;

    public AirspaceOverlay()
    {
        _transparentInputWindow = CreateTransparentWindow();
        _transparentInputWindow.PreviewMouseDown += TransparentInputWindow_PreviewMouseDown;
    }

    public object OverlayChild
    {
        get { return _transparentInputWindow.Content; }
        set { _transparentInputWindow.Content = value; }
    }

    private static Window CreateTransparentWindow()
    {
        var transparentInputWindow = new Window();

        //Make the window itself transparent, with no style.
        transparentInputWindow.Background = Brushes.Transparent;
        transparentInputWindow.AllowsTransparency = true;
        transparentInputWindow.WindowStyle = WindowStyle.None;

        //Hide from taskbar until it becomes a child
        transparentInputWindow.ShowInTaskbar = false;

        //HACK: This window and it's child controls should never have focus, as window styling of an invisible window 
        //will confuse user.
        transparentInputWindow.Focusable = false;

        return transparentInputWindow;
    }

    void TransparentInputWindow_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        _parentWindow.Focus();
    }

    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
    {
        base.OnRenderSizeChanged(sizeInfo);
        UpdateOverlaySize();
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        if (_transparentInputWindow.Visibility != Visibility.Visible)
        {
            UpdateOverlaySize();
            _transparentInputWindow.Show();
            _parentWindow = GetParentWindow(this);
            _transparentInputWindow.Owner = _parentWindow;
            _parentWindow.LocationChanged += ParentWindow_LocationChanged;
            _parentWindow.SizeChanged += ParentWindow_SizeChanged;
        }
    }

    private static Window GetParentWindow(DependencyObject o)
    {
        var parent = VisualTreeHelper.GetParent(o);
        if (parent != null)
            return GetParentWindow(parent);
        var fe = o as FrameworkElement;
        if (fe is Window)
            return fe as Window;
        if (fe != null && fe.Parent != null)
            return GetParentWindow(fe.Parent);  
        throw new ApplicationException("A window parent could not be found for " + o); 
    }

    private void ParentWindow_LocationChanged(object sender, EventArgs e)
    {
        UpdateOverlaySize();
    }

    private void ParentWindow_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        UpdateOverlaySize();
    }

    private void UpdateOverlaySize()
    {
        var hostTopLeft = PointToScreen(new Point(0, 0));
        _transparentInputWindow.Left = hostTopLeft.X;
        _transparentInputWindow.Top = hostTopLeft.Y;
        _transparentInputWindow.Width = ActualWidth;
        _transparentInputWindow.Height = ActualHeight;
    }
}

Try this on for size:

<hacks:AirspaceOverlay>
    <hacks:AirspaceOverlay.OverlayChild>
        <Canvas ToolTip = "A tooltip over a DirectX surface" Background="#01000000" Name="Overlay" />
    </hacks:AirspaceOverlay.OverlayChild>
    <controls:OpenGLControlWrappingWindowsFormsHost />
</hacks:AirspaceOverlay>


// Adapted from http://blogs.msdn.com/b/pantal/archive/2007/07/31/managed-directx-interop-with-wpf-part-2.aspx & http://www.4mghc.com/topics/69774/1/in-wpf-how-can-you-draw-a-line-over-a-windowsformshost
public class AirspaceOverlay : Decorator
{
    private readonly Window _transparentInputWindow;
    private Window _parentWindow;

    public AirspaceOverlay()
    {
        _transparentInputWindow = CreateTransparentWindow();
        _transparentInputWindow.PreviewMouseDown += TransparentInputWindow_PreviewMouseDown;
    }

    public object OverlayChild
    {
        get { return _transparentInputWindow.Content; }
        set { _transparentInputWindow.Content = value; }
    }

    private static Window CreateTransparentWindow()
    {
        var transparentInputWindow = new Window();

        //Make the window itself transparent, with no style.
        transparentInputWindow.Background = Brushes.Transparent;
        transparentInputWindow.AllowsTransparency = true;
        transparentInputWindow.WindowStyle = WindowStyle.None;

        //Hide from taskbar until it becomes a child
        transparentInputWindow.ShowInTaskbar = false;

        //HACK: This window and it's child controls should never have focus, as window styling of an invisible window 
        //will confuse user.
        transparentInputWindow.Focusable = false;

        return transparentInputWindow;
    }

    void TransparentInputWindow_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        _parentWindow.Focus();
    }

    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
    {
        base.OnRenderSizeChanged(sizeInfo);
        UpdateOverlaySize();
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        if (_transparentInputWindow.Visibility != Visibility.Visible)
        {
            UpdateOverlaySize();
            _transparentInputWindow.Show();
            _parentWindow = GetParentWindow(this);
            _transparentInputWindow.Owner = _parentWindow;
            _parentWindow.LocationChanged += ParentWindow_LocationChanged;
            _parentWindow.SizeChanged += ParentWindow_SizeChanged;
        }
    }

    private static Window GetParentWindow(DependencyObject o)
    {
        var parent = VisualTreeHelper.GetParent(o);
        if (parent != null)
            return GetParentWindow(parent);
        var fe = o as FrameworkElement;
        if (fe is Window)
            return fe as Window;
        if (fe != null && fe.Parent != null)
            return GetParentWindow(fe.Parent);  
        throw new ApplicationException("A window parent could not be found for " + o); 
    }

    private void ParentWindow_LocationChanged(object sender, EventArgs e)
    {
        UpdateOverlaySize();
    }

    private void ParentWindow_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        UpdateOverlaySize();
    }

    private void UpdateOverlaySize()
    {
        var hostTopLeft = PointToScreen(new Point(0, 0));
        _transparentInputWindow.Left = hostTopLeft.X;
        _transparentInputWindow.Top = hostTopLeft.Y;
        _transparentInputWindow.Width = ActualWidth;
        _transparentInputWindow.Height = ActualHeight;
    }
}
ゞ花落谁相伴 2024-11-13 13:14:57

这是迄今为止我在该主题上看到的最佳答案的链接:
我可以在顶部叠加 WPF 窗口吗另一个?

Here's a link to the best answer I've seen on this subject so far:
Can I overlay a WPF window on top of another?

赠佳期 2024-11-13 13:14:57

如果有人发现自己对这些修改不满意,可以选择将 WindowsFormsHost 的 Visibility 设置为 Collapsed 或 Hidden。

If anyone finds themselves unsatisfied with the hacks, setting the Visibility of the WindowsFormsHost to Collapsed or Hidden is always an option.

那伤。 2024-11-13 13:14:57

我在尝试创建托管 WinForms 控件的 MDI 样式界面,同时将 win 表单应用程序移植到 WPF 时遇到了这个问题。

我设法通过这样做来解决它:
WindowsFormsHost-> ElementHost-> WindowsFormsHost->我的胜利形式控件。

它非常丑陋,但它为 WPF 内容创建了窗口层,使其位于 WinForms 内容之下。

I came across this issue while trying to create a MDI style interface hosting WinForms controls while porting a win forms app to WPF.

I managed to solve it by doing something like this:
WindowsFormsHost -> ElementHost -> WindowsFormsHost -> my win forms controls.

Its super ugly, but it creates windows layers for the WPF content to be under the WinForms content.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文