xml 可拖动,非最顶层,单击以进行BringToFront弹出示例。 (ドラッグ可能で状态に応じて最顶层を切り替える弹出(クリックすると前面に来るよう调整済み))

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了xml 可拖动,非最顶层,单击以进行BringToFront弹出示例。 (ドラッグ可能で状态に応じて最顶层を切り替える弹出(クリックすると前面に来るよう调整済み))相关的知识,希望对你有一定的参考价值。

namespace NonTopmostPopupSample
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls.Primitives;
    using System.Windows.Input;
    using System.Windows.Interactivity;
    using System.Windows.Interop;

    namespace NativeApis
    {
        public class WinApi
        {
            [StructLayout(LayoutKind.Sequential)]
            public struct RECT
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
            }

            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

            [DllImport("user32.dll")]
            public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

            public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
            public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
            public static readonly IntPtr HWND_TOP = new IntPtr(0);
            public static readonly IntPtr HWND_BOTTOM = new IntPtr(1);

            public const UInt32 SWP_NOSIZE = 0x0001;
            public const UInt32 SWP_NOMOVE = 0x0002;
            public const UInt32 SWP_NOZORDER = 0x0004;
            public const UInt32 SWP_NOREDRAW = 0x0008;
            public const UInt32 SWP_NOACTIVATE = 0x0010;

            public const UInt32 SWP_FRAMECHANGED = 0x0020; /* The frame changed: send WM_NCCALCSIZE */
            public const UInt32 SWP_SHOWWINDOW = 0x0040;
            public const UInt32 SWP_HIDEWINDOW = 0x0080;
            public const UInt32 SWP_NOCOPYBITS = 0x0100;
            public const UInt32 SWP_NOOWNERZORDER = 0x0200; /* Don’t do owner Z ordering */
            public const UInt32 SWP_NOSENDCHANGING = 0x0400; /* Don’t send WM_WINDOWPOSCHANGING */

            public const UInt32 TOPMOST_FLAGS = SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSENDCHANGING;
        }		
    }

    namespace ExControls
    {
        using NativeApis;

        /// <summary>			
        /// Popup with code to not be the topmost control			
        /// </summary>			
        /// <remarks>			
        /// https://chriscavanagh.wordpress.com/2008/08/13/non-topmost-wpf-popup/			
        /// https://gist.github.com/flq/903202#file-nontopmostpopup-cs			
        /// </remarks>			
        public class NonTopmostPopup : Popup
        {
            /// <summary>			
            /// Is Topmost dependency property			
            /// </summary>			
            public static readonly DependencyProperty IsTopmostProperty = DependencyProperty.Register("IsTopmost", typeof(bool), typeof(NonTopmostPopup), new FrameworkPropertyMetadata(false, OnIsTopmostChanged));

            private bool? _appliedTopMost;
            private bool _alreadyLoaded;
            private Window _parentWindow;

            /// <summary>			
            /// Get/Set IsTopmost			
            /// </summary>			
            public bool IsTopmost
            {
                get { return (bool)GetValue(IsTopmostProperty); }
                set { SetValue(IsTopmostProperty, value); }
            }

            /// <summary>			
            /// ctor			
            /// </summary>			
            public NonTopmostPopup()
            {
                Loaded += OnPopupLoaded;
                Unloaded += OnPopupUnloaded;
            }


            void OnPopupLoaded(object sender, RoutedEventArgs e)
            {
                if (_alreadyLoaded)
                    return;

                _alreadyLoaded = true;

                if (Child != null)
                {
                    Child.AddHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(OnChildPreviewMouseLeftButtonDown), true);
                }

                _parentWindow = Window.GetWindow(this);

                if (_parentWindow == null)
                    return;

                _parentWindow.Activated += OnParentWindowActivated;
                _parentWindow.Deactivated += OnParentWindowDeactivated;
            }

            private void OnPopupUnloaded(object sender, RoutedEventArgs e)
            {
                if (_parentWindow == null)
                    return;
                _parentWindow.Activated -= OnParentWindowActivated;
                _parentWindow.Deactivated -= OnParentWindowDeactivated;
            }

            void OnParentWindowActivated(object sender, EventArgs e)
            {
                Debug.WriteLine("Parent Window Activated");
                SetTopmostState(true);
            }

            void OnParentWindowDeactivated(object sender, EventArgs e)
            {
                Debug.WriteLine("Parent Window Deactivated");

                if (IsTopmost == false)
                {
                    SetTopmostState(IsTopmost);
                }
            }

            void OnChildPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                Debug.WriteLine("Child Mouse Left Button Down");

                SetTopmostState(true);

                if (!_parentWindow.IsActive && IsTopmost == false)
                {
                    _parentWindow.Activate();
                    Debug.WriteLine("Activating Parent from child Left Button Down");
                }
            }

            private static void OnIsTopmostChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
            {
                var thisobj = (NonTopmostPopup)obj;

                thisobj.SetTopmostState(thisobj.IsTopmost);
            }

            protected override void OnOpened(EventArgs e)
            {
                SetTopmostState(IsTopmost);
                base.OnOpened(e);
            }

            private void SetTopmostState(bool isTop)
            {
                // Don’t apply state if it’s the same as incoming state			
                if (_appliedTopMost.HasValue && _appliedTopMost == isTop)
                {
                    return;
                }

                if (Child == null)
                    return;

                var hwndSource = (PresentationSource.FromVisual(Child)) as HwndSource;

                if (hwndSource == null)
                    return;
                var hwnd = hwndSource.Handle;

                WinApi.RECT rect;

                if (!WinApi.GetWindowRect(hwnd, out rect))
                    return;

                Debug.WriteLine("setting z-order " + isTop);

                if (isTop)
                {
                    WinApi.SetWindowPos(hwnd, WinApi.HWND_TOPMOST, rect.Left, rect.Top, (int)Width, (int)Height, WinApi.TOPMOST_FLAGS);
                }
                else
                {
                    // Z-Order would only get refreshed/reflected if clicking the			
                    // the titlebar (as opposed to other parts of the external			
                    // window) unless I first set the popup to HWND_BOTTOM			
                    // then HWND_TOP before HWND_NOTOPMOST			
                    WinApi.SetWindowPos(hwnd, WinApi.HWND_BOTTOM, rect.Left, rect.Top, (int)Width, (int)Height, WinApi.TOPMOST_FLAGS);
                    WinApi.SetWindowPos(hwnd, WinApi.HWND_TOP, rect.Left, rect.Top, (int)Width, (int)Height, WinApi.TOPMOST_FLAGS);
                    WinApi.SetWindowPos(hwnd, WinApi.HWND_NOTOPMOST, rect.Left, rect.Top, (int)Width, (int)Height, WinApi.TOPMOST_FLAGS);
                }

                _appliedTopMost = isTop;
            }
        }
    }

    namespace Behaviors
    {
        using NativeApis;

        /// <summary>			
        /// http://stackoverflow.com/questions/4784240/a-draggable-popup-control-in-wpf			
        /// </summary>			
        public class DragPopupBehavior : Behavior<Popup>
        {
            bool _mouseDown;
            Point _oldPosition;

            protected override void OnAttached()
            {
                base.OnAttached();

                AssociatedObject.MouseLeftButtonDown += AssociatedObject_MouseLeftButtonDown;
                AssociatedObject.MouseMove += AssociatedObject_MouseMove;
                AssociatedObject.MouseLeftButtonUp += AssociatedObject_MouseLeftButtonUp;
            }

            protected override void OnDetaching()
            {
                AssociatedObject.MouseLeftButtonDown -= AssociatedObject_MouseLeftButtonDown;
                AssociatedObject.MouseMove -= AssociatedObject_MouseMove;
                AssociatedObject.MouseLeftButtonUp -= AssociatedObject_MouseLeftButtonUp;

                base.OnDetaching();
            }

            void AssociatedObject_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
            {
                _mouseDown = false;
                AssociatedObject.Child.ReleaseMouseCapture();
            }

            void AssociatedObject_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
            {
                if (!_mouseDown)
                {
                    return;
                }

                var newPosition = AssociatedObject.PointToScreen(e.GetPosition(AssociatedObject));
                var offset = (newPosition - _oldPosition);
                _oldPosition = newPosition;

                AssociatedObject.HorizontalOffset += offset.X;
                AssociatedObject.VerticalOffset += offset.Y;

            }

            void AssociatedObject_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
            {
                _mouseDown = true;
                _oldPosition = AssociatedObject.PointToScreen(e.GetPosition(AssociatedObject));
                AssociatedObject.Child.CaptureMouse();
            }
        }

        public class ClickToBringToFrontPopupBehavior : Behavior<Popup>
        {
            protected override void OnAttached()
            {
                base.OnAttached();
                AssociatedObject.MouseLeftButtonDown += ExecMouseLeftButtonDown;
            }

            protected override void OnDetaching()
            {
                base.OnDetaching();
                AssociatedObject.MouseLeftButtonDown -= ExecMouseLeftButtonDown;
            }

            protected virtual void ExecMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                var window = Window.GetWindow(AssociatedObject);
                var hwndSource = (PresentationSource.FromVisual(AssociatedObject.Child)) as HwndSource;

                if (hwndSource == null)
                {
                    return;
                }

                var hwnd = hwndSource.Handle;

                WinApi.RECT rect;
                if (!WinApi.GetWindowRect(hwnd, out rect))
                {
                    return;
                }

                WinApi.SetWindowPos(hwnd, WinApi.HWND_TOPMOST, rect.Left, rect.Top, (int)window.Width, (int)window.Height, WinApi.TOPMOST_FLAGS);
            }
        }
    }
}
<Window					
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:exControls="clr-namespace:NonTopmostPopupSample.ExControls" 
    xmlns:behaviors="clr-namespace:NonTopmostPopupSample.Behaviors"
	xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
	xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
	x:Class="NonTopmostPopupSample.MainWindow"
    Title="Non Topmost Popup Sample"
	Height="426"
	Width="525"
	WindowState="Maximized">
    <Window.Resources>
        <Storyboard x:Key="ShowPopup">
            <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(Popup.IsOpen)" Storyboard.TargetName="popup1">
                <DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>
            </BooleanAnimationUsingKeyFrames>
            <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(Popup.IsOpen)" Storyboard.TargetName="popup2">
                <DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>
            </BooleanAnimationUsingKeyFrames>
            <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(Popup.IsOpen)" Storyboard.TargetName="popup3">
                <DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>
            </BooleanAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button">
            <BeginStoryboard x:Name="ShowPopup_BeginStoryboard" Storyboard="{StaticResource ShowPopup}"/>
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Main Screen" VerticalAlignment="Top" FontSize="64" Grid.RowSpan="2"/>
        <Button x:Name="button" Content="Show Popup" HorizontalAlignment="Left" Margin="10,240,0,0" VerticalAlignment="Top" Width="310" FontSize="26.667"/>
        <exControls:NonTopmostPopup x:Name="popup1" PopupAnimation="Scroll" AllowsTransparency="True" Placement="Center">
            <i:Interaction.Behaviors>
                <behaviors:DragPopupBehavior/>
                <behaviors:ClickToBringToFrontPopupBehavior/>
            </i:Interaction.Behaviors>
            <Grid Background="#FFE4A5A5" Height="250" Width="350">
                <TextBlock HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="popup 1" VerticalAlignment="Top" FontSize="29.333"/>
            </Grid>
        </exControls:NonTopmostPopup>
        <exControls:NonTopmostPopup x:Name="popup2" PopupAnimation="Fade" AllowsTransparency="True" Placement="Center" HorizontalOffset="500" VerticalOffset="50">
            <i:Interaction.Behaviors>
                <behaviors:DragPopupBehavior/>
                <behaviors:ClickToBringToFrontPopupBehavior/>
            </i:Interaction.Behaviors>
            <Grid Background="#FFA5CAE4" Height="250" Width="350">
                <TextBlock HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="popup 2" VerticalAlignment="Top" FontSize="29.333"/>
            </Grid>
        </exControls:NonTopmostPopup>
        <exControls:NonTopmostPopup x:Name="popup3" PopupAnimation="Slide" AllowsTransparency="True" Placement="Center" HorizontalOffset="-100" VerticalOffset="200" IsTopmost="False">
            <i:Interaction.Behaviors>
                <behaviors:DragPopupBehavior/>
                <behaviors:ClickToBringToFrontPopupBehavior/>
            </i:Interaction.Behaviors>
            <Grid Background="#FFE0DBA5" Height="250" Width="350">
                <TextBlock HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="popup 3" VerticalAlignment="Top" FontSize="29.333"/>
            </Grid>
        </exControls:NonTopmostPopup>
    </Grid>
</Window>

以上是关于xml 可拖动,非最顶层,单击以进行BringToFront弹出示例。 (ドラッグ可能で状态に応じて最顶层を切り替える弹出(クリックすると前面に来るよう调整済み))的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 可拖动的小部件,可以单击或拖动以移动到 DragTarget

如何通过在Vue中单击以编程方式触发可拖动的“移动”事件?

可以离开屏幕的可拖动叠加层?

通过单击和拖动进行多重选择

单击时将图像添加到屏幕并允许其可拖动/可旋转

jQueryUI 可排序和可拖动目标不会水平滚动以进行放置,但会进行排序