-
-
Save flq/903202 to your computer and use it in GitHub Desktop.
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 | |
} |
Can any one please share a sample project with WebBrowserControl of WPF if possible ( or any ) for reference of use of class.
please share the sample project!
This works awesome, but I am facing a small problem when I drag the parent window the pop up does not move with the parent window. It looks like pop up is not the part of application. Can you please let me know how I can move the popup along with the window?
But this popup control doesn't set initial focus to itself or any of its child control.how to do it??
That works great, thanks! But would you mind to add a license for this?
it works!
This works awesome, but I am facing a small problem when I drag the parent window the pop up does not move with the parent window. It looks like pop up is not the part of application. Can you please let me know how I can move the popup along with the window?
_parentWindow.LocationChanged += _parentWindow_LocationChanged; private void _parentWindow_LocationChanged(object sender, System.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; } }
That works great, thanks! But would you mind to add a license for this?
Apache 2
Excelent, this works.
Thanks.