Drop a window into another window

前端 未结 1 533
被撕碎了的回忆
被撕碎了的回忆 2021-01-17 11:57

My drop event

private void Window_Drop(object sender, DragEventArgs e)
{
    var window = e.Data.GetData(typeof(Window)) as Window;
    if (window != null)
          


        
1条回答
  •  说谎
    说谎 (楼主)
    2021-01-17 12:56

    It sounds like you are trying to implement a docking system. Have you had a look at existing Docking Managers.

    Avalon Dock is a great Open Source example. It's well documented and easy to use.

    If you're determined to implement your own, you can try to find if there is a Window beneath the one you are dragging. Unfortunately WPF doesn't have an easy way to HitTest across Windows. The way around this would be to make some Win32 calls. The code used is from another SO thread here, by Ray Burns and a Win32 call for getting the current mouse position, by Fredrik Hedblad.

    I've also used WindowStyle="None" and implemented a custom title bar for the window so I can catch mouse events on the window.

    I'm not entirely sure how you have implemented the tab dragging to create a new window but if that is working you can do the following.

    XAML

    
    
        
    
    
        
    
    

    Code

    public partial class DraggedWindow : Window
    {
        private readonly MainWindow _mainWindow;
        private bool _isDropped = false;
    
        public DraggedWindow(MainWindow mainWindow)
        {
            _mainWindow = mainWindow;
            InitializeComponent();
            DataContext = new TabItem() { Header = "TabItem6", Content = "Content6" };
        }
    
        const uint GW_HWNDNEXT = 2;
    
        [DllImport("User32")]
        static extern IntPtr GetTopWindow(IntPtr hWnd);
        [DllImport("User32")]
        static extern IntPtr GetWindow(IntPtr hWnd, uint wCmd);
        [DllImport("User32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetCursorPos(ref Win32Point pt);
    
        [StructLayout(LayoutKind.Sequential)]
        internal struct Win32Point
        {
            public Int32 X;
            public Int32 Y;
        };
    
        public static Point GetMousePosition()
        {
            Win32Point w32Mouse = new Win32Point();
            GetCursorPos(ref w32Mouse);
            return new Point(w32Mouse.X, w32Mouse.Y);
        }
    
        public Window FindWindowUnderThisAt(Point screenPoint)  // WPF units (96dpi), not device units
        {
            return (
              from win in SortWindowsTopToBottom(Application.Current.Windows.OfType())
              where new Rect(win.Left, win.Top, win.Width, win.Height).Contains(screenPoint)
              && !Equals(win, this)
              select win
            ).FirstOrDefault();
        }
    
        public IEnumerable SortWindowsTopToBottom(IEnumerable unsorted)
        {
            var byHandle = unsorted.ToDictionary(win =>
                ((HwndSource)PresentationSource.FromVisual(win)).Handle);
    
            for (IntPtr hWnd = GetTopWindow(IntPtr.Zero); hWnd != IntPtr.Zero; hWnd = GetWindow(hWnd, GW_HWNDNEXT))
            {
                if (byHandle.ContainsKey(hWnd))
                    yield return byHandle[hWnd];
            }
        }
    
        private void DraggedWindow_OnMouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                this.DragMove();
            }
    
            var absoluteScreenPos = GetMousePosition();
            var windowUnder = FindWindowUnderThisAt(absoluteScreenPos);
            if (windowUnder != null && windowUnder.Equals(_mainWindow))
            {
                if (_isDropped)
                {
                    // Your code here
                    var tabitem = new TabItem();
                    tabitem.Content = (DataContext as TabItem).Content;
                    tabitem.Header = (DataContext as TabItem).Header;
                    _mainWindow.TabControl1.Items.Add(tabitem);
                    this.Close();
                }
            }
        }
    
        private void DraggedWindow_OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            _isDropped = false;
        }
    
        private void DraggedWindow_OnMouseUp(object sender, MouseButtonEventArgs e)
        {
            _isDropped = true;
        }
    }
    

    Main Window Xaml (example)

    
    
        
            Content1
            Content2
            Content3
            Content4
            Content5
        
    
    

    Main Window Code (example)

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            new DraggedWindow(this).Show();
        }
    }
    

    0 讨论(0)
提交回复
热议问题