2011-05-12 21 views
8

Sé que el comportamiento predeterminado de WPF es representar controles WPF y luego renderizar WinForms, pero ¿hay alguna manera de mostrar WPF encima de WindowsFormsHost?Renderizar control WPF encima de WindowsFormsHost

Editar: He encontrado un hack de temperatura también. Cuando el control de WPF se superpone WindowsFormsHost, puedo cambiar el tamaño de las WindowsFormsHost (Esto sólo funciona cuando se tiene objeto rectangular que se solapa, no funciona para otras formas.)

+0

Una forma de hacerlo es superponer otra ventana ontop con opacidad y transparencia, funciona bien siempre que use material de pantalla completa –

Respuesta

5

Este problema "espacio aéreo" es suppose to be fixed en WPF vNext. Hay un par de soluciones, como here, here y here.

Una forma de hacerlo es alojar el contenido de WPF en una ventana emergente o ventana transparente, que se superpone al contenido de Interop.

+5

NOTA: Comenta esto como un intento de no hacer las ilusiones de quien lea esto, el "espacio aéreo" "El problema en el artículo publicado de @ CodeNaked tenía una solución (hwndhost.IsRedirected) implementada en .NET 4.5 beta, pero luego se soltó en la versión final por cualquier razón. Lea [esto] (http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/2644120-bring-back-the-hwndhost-isredirected-and-compositi), y [this] (http://social.msdn.microsoft.com/Forums/vstudio/en-US/3a171a12-399c-450b-8ed9-9320e8a6dfce/wpf-45-beta-hwndhostisredirected-and-compositionmode-removed-permanently?forum=wpf) –

3

Pruebe esto en el tamaño:

<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; 
    } 
} 
2

Si alguien encuentra a sí mismos insatisfecho con los cortes, el establecimiento la Visibilidad de WindowsFormsHost a Colapsada u Oculta es siempre una opción.

7

Tarde en la fiesta, lo sé, pero recientemente me encontré con este problema usando un control WebBrowser.

La solución definitiva era crear una captura de pantalla del navegador web cada vez que albergaba un cuadro de diálogo modal en la parte superior. Dado que este era un poco incómoda, le di vuelta en un proyecto de Github, es de esperar que esto ayude un poco -

https://github.com/chris84948/AirspaceFixer

(Está en Nuget también, bajo AirspaceFixer)

Una vez que tenga el proyecto todo lo que hay que hacer es esta

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

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

Dónde FixAirspace es la propiedad de dependencia que pasa de la vista "real" de los contenidos, a la captura de pantalla o ver "falso".