使用自定义Popup控件,解决WPF控件被Winform遮挡、初始化时Z顺序错误导致显隐异常、输入框无法输入的问题,还可以设置Popup以全屏方式展现。

public class CusPopup : Popup
{/// <summary>/// 应用状态/// </summary>private bool? _appliedTopMost;/// <summary>/// 是否已经加载/// </summary>private bool _alreadyLoaded;/// <summary>/// popup所在的窗体/// </summary>private Window _parentWindow;/// <summary>/// 是否顶置/// </summary>public bool IsTopmost{get { return (bool)GetValue(IsTopmostProperty); }set { SetValue(IsTopmostProperty, value); }}/// <summary>/// 是否顶置依赖属性(默认不顶置)/// </summary>public static readonly DependencyProperty IsTopmostProperty = DependencyProperty.Register("IsTopmost", typeof(bool), typeof(CusPopup), new FrameworkPropertyMetadata(false, OnIsTopmostChanged));/// <summary>/// 是否跟随父窗体移动(默认为True)/// </summary>public bool IsMove{get { return (bool)GetValue(IsMoveProperty); }set { SetValue(IsMoveProperty, value); }}public static readonly DependencyProperty IsMoveProperty =DependencyProperty.Register("IsMove", typeof(bool), typeof(CusPopup), new PropertyMetadata(true));/// <summary>/// 是否包含TextBox控件/// </summary>public bool IsHasTextBox{get { return (bool)GetValue(IsHasTextBoxProperty); }set { SetValue(IsHasTextBoxProperty, value); }}public static readonly DependencyProperty IsHasTextBoxProperty =DependencyProperty.Register("IsHasTextBox", typeof(bool), typeof(CusPopup), new PropertyMetadata(false));/// <summary>/// 是否全屏/// </summary>public bool IsFullScreen{get { return (bool)GetValue(IsFullScreenProperty); }set { SetValue(IsFullScreenProperty, value); }}public static readonly DependencyProperty IsFullScreenProperty =DependencyProperty.Register("IsFullScreen", typeof(bool), typeof(CusPopup), new PropertyMetadata(false, OnFullScreenChanged));/// <summary>/// 全屏设置改变事件/// </summary>/// <param name="d"></param>/// <param name="e"></param>private static void OnFullScreenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){CusPopup pop = (CusPopup)d;if((bool)e.NewValue == true){pop.Opened += Pop_Opened;}}/// <summary>/// 全屏时打开pop事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private static void Pop_Opened(object sender, EventArgs e){Popup pop = sender as Popup;DependencyObject parent = pop.Child;do{parent = System.Windows.Media.VisualTreeHelper.GetParent(parent);if (parent != null && parent.ToString() == "System.Windows.Controls.Primitives.PopupRoot"){var element = parent as FrameworkElement;var mainWin = Application.Current.MainWindow;element.Height = mainWin.ActualHeight;element.Width = mainWin.ActualWidth;break;}}while (parent != null);}/// <summary>/// 构造函数/// </summary>public CusPopup(){Loaded += OnPopupLoaded;Unloaded += OnPopupUnloaded;}/// <summary>/// popup加载事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>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 (IsMove)_parentWindow.LocationChanged += delegate{var offset = this.HorizontalOffset;this.HorizontalOffset = offset + 1;this.HorizontalOffset = offset;};if (_parentWindow == null)return;_parentWindow.Activated += OnParentWindowActivated;_parentWindow.Deactivated += OnParentWindowDeactivated;//SetPopupOwner();}private void OnPopupUnloaded(object sender, RoutedEventArgs e){if (_parentWindow == null)return;_parentWindow.Activated -= OnParentWindowActivated;_parentWindow.Deactivated -= OnParentWindowDeactivated;}private void SetPopupOwner(){if (this == null) return;var hwndSource = (PresentationSource.FromVisual(this)) as HwndSource;if (hwndSource == null) return;var hwnd = hwndSource.Handle;WindowInteropHelper helper = new WindowInteropHelper(_parentWindow);SetWindowLong(hwnd, -8, new IntPtr(helper.Handle.ToInt32()));}/// <summary>/// 主窗体激活事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>void OnParentWindowActivated(object sender, EventArgs e){Debug.WriteLine("Parent Window Activated");SetTopmostState(true);}/// <summary>/// 主窗体不在激活状态事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>void OnParentWindowDeactivated(object sender, EventArgs e){if (IsTopmost == false){SetTopmostState(IsTopmost);}}/// <summary>/// 子元素的鼠标左键按下事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>void OnChildPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e){//SetTopmostState(true);if (IsHasTextBox){ActivatePopup();}else{if (!_parentWindow.IsActive && IsTopmost == false){_parentWindow.Activate();}}}/// <summary>/// IsTopmost属性改变事件/// </summary>/// <param name="obj"></param>/// <param name="e"></param>private static void OnIsTopmostChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e){var thisobj = (CusPopup)obj;thisobj.SetTopmostState(thisobj.IsTopmost);}/// <summary>/// 重写open事件/// </summary>/// <param name="e"></param>protected override void OnOpened(EventArgs e){//设置状态SetTopmostState(IsTopmost);base.OnOpened(e);}/// <summary>/// 设置置顶状态/// </summary>/// <param name="isTop"></param>private void SetTopmostState(bool isTop){// 如果状态与输入状态相同,则不要应用状态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);//设置所有者窗口,跟随其所有者窗口的Z序显示,避免失去焦点后被遮盖var windowHwnd = new WindowInteropHelper(_parentWindow).Handle;SetWindowLong(hwnd, -8, windowHwnd);if (isTop){SetWindowPos(hwnd, HWND_TOPMOST, rect.Left, rect.Top, (int)Width, (int)Height, TOPMOST_FLAGS);}else{/*z顺序只会在点击时得到刷新/反射标题栏(与外部的其他部分相对比窗口)除非我先将弹出窗口设置为hwndbottom然后HWND_TOP 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;}[DllImport("USER32.DLL")]public static extern IntPtr SetFocus(IntPtr hWnd);/// <summary>/// 激活Pop(解决无法删除TextBox文字)/// </summary>/// <param name="popup"></param>public void ActivatePopup(){if (Child == null) return;//try to get a handle on the popup itself (via its child)HwndSource source = (HwndSource)PresentationSource.FromVisual(Child);IntPtr handle = source.Handle;//activate the popupSetFocus(handle);}#region P / Invoke 入口和定义[StructLayout(LayoutKind.Sequential)]public struct RECT{public int Left;public int Top;public int Right;public int Bottom;}[DllImport("user32.dll", SetLastError = true)]static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);[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;#endregion
}

WPF解决Popup窗口随动及显隐相关推荐

  1. 关于WPF中Popup中的一些用法的总结

    原文:关于WPF中Popup中的一些用法的总结 Popup控件是一个常用的非常有用的控件,顾明思义就是弹出式控件,首先我们来看看MSDN对它的解释吧,表示具有内容的弹出窗口,这个是非常重要的控件,我们 ...

  2. WPF的Popup控件使用

    WPF控件学习总结系统系列 文章目录 WPF控件学习总结系统系列 前言 一.使用场景 二.使用步骤 1.前端界面 2.属性说明 展示效果 总结 参考学习出处 前言 WPF使用popup控件实现弹出式提 ...

  3. [WPF疑难]避免窗口最大化时遮盖任务栏

    [WPF疑难]避免窗口最大化时遮盖任务栏 周银辉 WPF窗口最大化时有个很不好的现象是:如果窗口的WindowStyle被直接或间接地设置为None后(比如很多情况下你会覆盖默认的窗体样式,即不采用W ...

  4. [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口

    原文:[WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口 [WPF疑难] 模式窗口被隐藏后重新显示时变成了非模式窗口 周银辉 现象: 大家可以试试下面这个很有趣但会带来Defect的现象:当我 ...

  5. 在popup窗口中俘获事件的缺陷修复

    我们在处理HTML元素的事件时,通常可以使用两种方法来添加其处理函数.一是直接向HTML元素的事件处理回调(如:onclick.onlond等)赋值:一是使用元素的attachEvent()方法来添加 ...

  6. wpf之默认窗口模板研究

    wpf默认的窗口模板,真的好丑好丑.但是,非常不满意的上面的边框居然不让修改.今天决定使用Blend对默认的窗口模板进行研究. 使用blend新建一个项目 右键窗口,点击编辑模板--->编辑副本 ...

  7. 极点五笔状态栏和候选窗口显隐

    目录: 一.简述 二.困扰解决 困扰一:输入法的状态栏消失不见 困扰二:候选窗口消失不见,无法选择汉字 困扰三:无法打出生僻字 三.查看设置状态另一法 ------------------------ ...

  8. WPF绘制自定义窗口

    原文:WPF绘制自定义窗口 WPF是制作界面的一大利器,下面就用WPF模拟一下360的软件管理界面,360软件管理界面如下: 界面不难,主要有如下几个要素: 窗体的圆角 自定义标题栏及按钮 自定义状态 ...

  9. 解决Echarts窗口自适应失效问题

    解决Echarts窗口自适应失效问题 参考文章: (1)解决Echarts窗口自适应失效问题 (2)https://www.cnblogs.com/chuanqi1995/p/11543765.htm ...

最新文章

  1. vue使用pwa_如何使用HTML,CSS和JavaScript从头开始构建PWA
  2. UI设计APP图标设计规范介绍
  3. 惊艳!基于RNN的AI写词机竟能写出如此优秀的情诗!
  4. 3764树上的异或值(自己研究的静态字典树)
  5. acwing----春季每日一题2022篇(一)
  6. shell脚本游戏之:剪刀石头布
  7. 8 cocos2dx添加场景切换效果,控制场景切换彻底完成之后再执行动画
  8. sessionFactory.getCurrent()和sessionFactory.openSession()的区别
  9. [转]树结构表递归查询在ORACLE和MSSQL中的实现方法
  10. JMetro版本5.2已发布
  11. [BZOJ 2165] 大楼 【DP + 倍增 + 二进制】
  12. Metasploit Framework命令汇总
  13. 【数据湖加速篇】 —— 如何利用缓存加速服务来提升数据湖上机器学习训练速度
  14. 【pytorch】.detach() .detach_() 和 .data==>用于切断反向传播
  15. java基本语法心得_Java学习笔记(一)——基础语法(上)
  16. word2vec需要去标点吗_word2vec训练词向量前期处理-中文分词等
  17. 2015中国银联业务(武汉)面试经验(软件开发)
  18. nbu mysql_mysql数据备份之NBU
  19. html在线生成字体,手写字体在线生成
  20. react引入html2canvas和jspdf生成PDF打印及下载

热门文章

  1. 三聚氰胺的婴幼儿奶粉排行榜
  2. DVWA-寻找默认登录密码
  3. 【算法】最短路径--Hdu2066 一个人的旅行
  4. 激​发​团​队​工​作​热​情​:​领​导​者​的​职​责
  5. html5控件结构图,OrgChart组织架构图控件
  6. 7-38 支票面额 (C语言)
  7. [跟着需求出方案,跟着方案学运维]批量修复漏洞-ssh弱密钥交换算法
  8. MySQL插入datetime类型字段
  9. 欣博阅G10 开机老是停止于开机界面
  10. 振华风光半导体IPO过会:年营收5亿 中国电子是大股东