在程序写一个popup发现他会在置顶,在网上找了两大神代码,就使用他的代码
http://www.cnblogs.com/Leaco/p/3164394.html
http://blog.csdn.net/baijinwen/article/details/6159043
只需要把下面的类放到自己的软件,然后把使用 popup 替换为 CCPopup 就不会让popup置顶
public class CCPopup : Popup
{
public static DependencyProperty TopmostProperty = Window.TopmostProperty.AddOwner(typeof(CCPopup), 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 CCPopup).UpdateWindow();
}
protected override void OnOpened(EventArgs e)
{
UpdateWindow();
}
private void UpdateWindow()
{
var hwnd = ((HwndSource)PresentationSource.FromVisual(this.Child)).Handle;
RECT rect;
if (GetWindowRect(hwnd, out rect))
{
SetWindowPos(hwnd, Topmost ? -1 : -2, rect.Left, rect.Top, (int)this.Width, (int)this.Height, 0);
}
}
#region P/Invoke imports & definitions
[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)]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32", EntryPoint = "SetWindowPos")]
private static extern int SetWindowPos(IntPtr hWnd, int hwndInsertAfter, int x, int y, int cx, int cy, int wFlags);
#endregion
}
代码:
using System; | |
using System.Diagnostics; | |
using System.Runtime.InteropServices; | |
using System.Windows; | |
using System.Windows.Controls.Primitives; | |
using System.Windows.Input; | |
using System.Windows.Interop; | |
/// <summary> | |
/// Popup with code to not be the topmost control | |
/// </summary> | |
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; | |
RECT rect; | |
if (!GetWindowRect(hwnd, out rect)) | |
return; | |
Debug.WriteLine("setting z-order " + isTop); | |
if (isTop) | |
{ | |
SetWindowPos(hwnd, HWND_TOPMOST, rect.Left, rect.Top, (int)Width, (int)Height, 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 | |
SetWindowPos(hwnd, HWND_BOTTOM, rect.Left, rect.Top, (int)Width, (int)Height, TOPMOST_FLAGS); | |
SetWindowPos(hwnd, HWND_TOP, rect.Left, rect.Top, (int)Width, (int)Height, TOPMOST_FLAGS); | |
SetWindowPos(hwnd, HWND_NOTOPMOST, rect.Left, rect.Top, (int)Width, (int)Height, TOPMOST_FLAGS); | |
} | |
_appliedTopMost = isTop; | |
} | |
#region P/Invoke imports & definitions | |
#pragma warning disable 1591 //Xml-doc | |
#pragma warning disable 169 //Never used-warning | |
// ReSharper disable InconsistentNaming | |
// Imports etc. with their naming rules | |
[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)] | |
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); | |
[DllImport("user32.dll")] | |
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, | |
int Y, int cx, int cy, uint uFlags); | |
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); | |
static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2); | |
static readonly IntPtr HWND_TOP = new IntPtr(0); | |
static readonly IntPtr HWND_BOTTOM = new IntPtr(1); | |
private const UInt32 SWP_NOSIZE = 0x0001; | |
const UInt32 SWP_NOMOVE = 0x0002; | |
const UInt32 SWP_NOZORDER = 0x0004; | |
const UInt32 SWP_NOREDRAW = 0x0008; | |
const UInt32 SWP_NOACTIVATE = 0x0010; | |
const UInt32 SWP_FRAMECHANGED = 0x0020; /* The frame changed: send WM_NCCALCSIZE */ | |
const UInt32 SWP_SHOWWINDOW = 0x0040; | |
const UInt32 SWP_HIDEWINDOW = 0x0080; | |
const UInt32 SWP_NOCOPYBITS = 0x0100; | |
const UInt32 SWP_NOOWNERZORDER = 0x0200; /* Don’t do owner Z ordering */ | |
const UInt32 SWP_NOSENDCHANGING = 0x0400; /* Don’t send WM_WINDOWPOSCHANGING */ | |
const UInt32 TOPMOST_FLAGS = | |
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSENDCHANGING; | |
// ReSharper restore InconsistentNaming | |
#pragma warning restore 1591 | |
#pragma warning restore 169 | |
#endregion | |
} |
如果看不到上面代码,请点击 https://gist.github.com/flq/903202
另外的已知问题
本文会经常更新,请阅读原文: https://blog.lindexi.com/post/WPF-popup%E7%BD%AE%E9%A1%B6.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
如果你想持续阅读我的最新博客,请点击 RSS 订阅,推荐使用RSS Stalker订阅博客,或者收藏我的博客导航
本作品采用
知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议
进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:
https://blog.lindexi.com
),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请
与我联系
。
无盈利,不卖课,做纯粹的技术博客
以下是广告时间
推荐关注 Edi.Wang 的公众号
欢迎进入 Eleven 老师组建的 .NET 社区
以上广告全是友情推广,无盈利