none
WPF Element über einem HwndHost RRS feed

  • Frage

  • Hallo,

    ich habe folgendes Problem. Ich will über ein WIN32 gehostetes Window ein WPF Control legen. Leider sagt die MSDN, dass die gehosteten Fenster immer über den WPF Elementen liegen (mit einigen Ausnahmen Menü, Popup ...). Vielleicht weiß jemand von euch einen Workaround, wie man dies trotzdem erreichen könnte.

    Beispielcode unten.

    Gruß

    Klaus

     

    Das HwndControl, mein Fenser (Hauptfenster) und der dazugehörige Codebehind:

    using System;
    using System.Runtime.InteropServices;
    using System.Windows.Interop;
    
    namespace MapHost
    {
      public class MapControl : HwndHost
      {
        internal const int
           WS_CHILD = 0x40000000,
           WS_VISIBLE = 0x10000000,
           LBS_NOTIFY = 0x00000001,
           HOST_ID = 0x00000002,
           LISTBOX_ID = 0x00000001,
           WS_VSCROLL = 0x00200000,
           WS_BORDER = 0x00800000;
    
        IntPtr hwndHost;
    
        private int hostWidth;
        private int hostHeight;
    
        public MapControl(double height, double width)
        {
          hostHeight = (int)height;
          hostWidth = (int)width;
        }
        
        protected override HandleRef BuildWindowCore(HandleRef hwndParent)
        {
          hwndHost = IntPtr.Zero;
    
          hwndHost = CreateWindowEx(0, "static", "",
                       WS_CHILD | WS_VISIBLE,
                       0, 0,
                       hostWidth, hostHeight,
                       hwndParent.Handle,
                       (IntPtr)HOST_ID,
                       IntPtr.Zero,
                       0);
          return new HandleRef(this, hwndHost);
        }
    
        [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Unicode)]
        internal static extern IntPtr CreateWindowEx(int dwExStyle,
                               string lpszClassName,
                               string lpszWindowName,
                               int style,
                               int x, int y,
                               int width, int height,
                               IntPtr hwndParent,
                               IntPtr hMenu,
                               IntPtr hInst,
                               [MarshalAs(UnmanagedType.AsAny)] object pvParam);
        
        protected override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
          handled = false;
          return IntPtr.Zero;
        }
    
        protected override void DestroyWindowCore(HandleRef hwnd)
        {
          DestroyWindow(hwnd.Handle);
        }
    
        [DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Unicode)]
        internal static extern bool DestroyWindow(IntPtr hwnd);
    
    
      }
    }
    
    <Window x:Class="MapHost.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        Top="100" Left="100"
        xmlns:local="clr-namespace:MapHost">
      <DockPanel>
        <Button Content="Test" DockPanel.Dock="Bottom" Click="Button_Click"/>
        <Grid>
          <Border Background="Red" x:Name="m_HwndHostBorder"/>
          <Canvas x:Name="m_Canvas">
            <Rectangle Canvas.Top="50" Canvas.Left="50" Width="100" Height="100" Stroke="Aqua" Fill="Aquamarine"/>
          </Canvas>
        </Grid>
      </DockPanel>
    </Window>
    
    using System.Windows;
    
    namespace MapHost
    {
      /// <summary>
      /// Interaction logic for MainWindow.xaml
      /// </summary>
      public partial class MainWindow : Window
      {
        public MainWindow()
        {
          InitializeComponent();
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          MapControl control = new MapControl(m_HwndHostBorder.ActualWidth, m_HwndHostBorder.ActualHeight);
          m_HwndHostBorder.Child = control;
    
          m_Canvas.InvalidateVisual();
        }
      }
    }
    

     

    Freitag, 18. Juni 2010 19:55

Antworten

  • Hallo Robert,

    danke für die Links. Die sind einige ganz interessant, aber trotzdem finde ich darin keine einzige Möglichkeit WPF Elemente über ein HWndHost zu setzen. Tatsächlich steht da sogar:

    In http://blogs.msdn.com/b/nickkramer/archive/2005/07/14/438640.aspx:

    "HwndHost will appear on top of other Avalon elements in the same top-level window. (But note that menus, ToolTips, and combo box drop-downs are separate top-level windows, and so should work fine with HwndHost.)  This is because multiple Avalon elements share a single hwnd, and you can't say to Win32, "please put this hosted hwnd in front of only some parts of the Avalon hwnd."

    Was mich langsam daran zweifeln lässt, dass es überhaupt eine Möglichkeit gibt :(

    Gruß

    Klaus


    Dienstag, 6. Juli 2010 15:26

Alle Antworten