You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.5 KiB
138 lines
4.5 KiB
using System; |
|
using System.Collections.Generic; |
|
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.Interop; |
|
using System.Windows.Media; |
|
|
|
namespace Kingo.Plugin.DataCheck.Views |
|
{ |
|
public class PopupEx : Popup |
|
{ |
|
/// <summary> |
|
/// 是否窗口随动,默认为随动(true) |
|
/// </summary> |
|
public bool IsPositionUpdate |
|
{ |
|
get { return (bool)GetValue(IsPositionUpdateProperty); } |
|
set { SetValue(IsPositionUpdateProperty, value); } |
|
} |
|
|
|
public static readonly DependencyProperty IsPositionUpdateProperty = |
|
DependencyProperty.Register("IsPositionUpdate", typeof(bool), typeof(PopupEx), new PropertyMetadata(true, new PropertyChangedCallback(IsPositionUpdateChanged))); |
|
|
|
private static void IsPositionUpdateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|
{ |
|
(d as PopupEx).pup_Loaded(d as PopupEx, null); |
|
} |
|
|
|
/// <summary> |
|
/// 加载窗口随动事件 |
|
/// </summary> |
|
public PopupEx() |
|
{ |
|
this.Loaded += pup_Loaded; |
|
} |
|
|
|
/// <summary> |
|
/// 加载窗口随动事件 |
|
/// </summary> |
|
private void pup_Loaded(object sender, RoutedEventArgs e) |
|
{ |
|
Popup pup = sender as Popup; |
|
var win = VisualTreeHelper.GetParent(pup); |
|
while (win != null && (win as Window) == null) |
|
{ |
|
win = VisualTreeHelper.GetParent(win); |
|
} |
|
if ((win as Window) != null) |
|
{ |
|
(win as Window).LocationChanged -= PositionChanged; |
|
(win as Window).SizeChanged -= PositionChanged; |
|
if (IsPositionUpdate) |
|
{ |
|
(win as Window).LocationChanged += PositionChanged; |
|
(win as Window).SizeChanged += PositionChanged; |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// 刷新位置 |
|
/// </summary> |
|
private void PositionChanged(object sender, EventArgs e) |
|
{ |
|
try |
|
{ |
|
var method = typeof(Popup).GetMethod("UpdatePosition", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); |
|
if (this.IsOpen) |
|
{ |
|
method.Invoke(this, null); |
|
} |
|
} |
|
catch |
|
{ |
|
return; |
|
} |
|
} |
|
|
|
//是否最前默认为非最前(false) |
|
public static DependencyProperty TopmostProperty = Window.TopmostProperty.AddOwner(typeof(Popup), new FrameworkPropertyMetadata(false, OnTopmostChanged)); |
|
public bool Topmost |
|
{ |
|
get { return (bool)GetValue(TopmostProperty); } |
|
set { SetValue(TopmostProperty, value); } |
|
} |
|
private static void OnTopmostChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) |
|
{ |
|
(obj as PopupEx).UpdateWindow(); |
|
} |
|
|
|
/// <summary> |
|
/// 重写拉开方法,置于非最前 |
|
/// </summary> |
|
/// <param name="e"></param> |
|
protected override void OnOpened(EventArgs e) |
|
{ |
|
UpdateWindow(); |
|
} |
|
|
|
/// <summary> |
|
/// 刷新Popup层级 |
|
/// </summary> |
|
private void UpdateWindow() |
|
{ |
|
var hwnd = ((HwndSource)PresentationSource.FromVisual(this.Child)).Handle; |
|
RECT rect; |
|
if (NativeMethods.GetWindowRect(hwnd, out rect)) |
|
{ |
|
NativeMethods.SetWindowPos(hwnd, Topmost ? -1 : -2, rect.Left, rect.Top, (int)this.Width, (int)this.Height, 0); |
|
} |
|
} |
|
|
|
[StructLayout(LayoutKind.Sequential)] |
|
public struct RECT |
|
{ |
|
public int Left; |
|
public int Top; |
|
public int Right; |
|
public int Bottom; |
|
} |
|
#region P/Invoke imports & definitions |
|
public static class NativeMethods |
|
{ |
|
|
|
|
|
[DllImport("user32.dll")] |
|
[return: MarshalAs(UnmanagedType.Bool)] |
|
internal static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); |
|
[DllImport("user32", EntryPoint = "SetWindowPos")] |
|
internal static extern int SetWindowPos(IntPtr hWnd, int hwndInsertAfter, int x, int y, int cx, int cy, int wFlags); |
|
} |
|
#endregion |
|
} |
|
}
|
|
|