本文介绍几种使利用始终置于顶层的办法。
问题形容
个别状况下,想要将利用置于顶层,设置其TopMost属性为true即可。对于多个设置了TopMost属性的利用,后激活的在下面。
但有的利用,比方全局的快捷操作工具条,它须要在所有利用之上,即便是设置了TopMost的利用。
解决思路
留神:使某个利用永远不会被其它利用笼罩,这自身是个伪命题。因为如果有两个程序(A和B)这样做,拖动两个窗口使它们重叠,这两个窗口中的一个必须在另一个之上,这在逻辑上是互相矛盾的。
所以应该尽量避免这种状况,如果非要这样做,本文提供如下几种方法实现(不要将两个这样的利用重叠,否则会不停将置顶)。
首先,该应用程序须要设置其TopMost属性为true,这样一般窗口自身就会在它上面。本文次要探讨该窗口如何置于设置了TopMost属性的窗口之上。
计划一:捕捉WM_WINDOWPOSCHANGING音讯
咱们晓得,应用Win32的SetWindowPos接口能够扭转窗口的Z Order,能够猜想,当另外一个利用置顶时,咱们的利用会扭转其Z Order,因而,咱们能够尝试捕捉WM_WINDOWPOSCHANGING音讯。
当窗口的大小、地位、Z序扭转时,窗口会接管到WM_WINDOWPOSCHANGING音讯,咱们能够应用WndProc解决窗口音讯。当捕捉到该音讯时,咱们能够尝试将利用再次置顶。要害代码如下,测试可行,但不确定是否有副作用:
/// <summary>/// 计划一:捕捉WM_WINDOWPOSCHANGING音讯,若无SWP_NOZORDER标记,则置顶/// </summary>private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled){ switch (msg) { case Win32Api.WM_WINDOWPOSCHANGING: Win32Api.WINDOWPOS wp = (Win32Api.WINDOWPOS)Marshal.PtrToStructure( lParam, typeof(Win32Api.WINDOWPOS)); if ((wp.flags & Win32Api.SWP_NOZORDER) == 0) _ = SetTopMostLater(); // 不应用弃元编译器会收回正告 break; } return IntPtr.Zero;}private async Task SetTopMostLater(){ await Task.Delay(300); var interopHelper = new WindowInteropHelper(this); Win32Api.SetWindowPos(interopHelper.Handle, Win32Api.HWND_TOPMOST, 0, 0, 0, 0, Win32Api.TOPMOST_FLAGS);}
计划二:循环置顶
这个是比拟容易想到的一个计划,每隔肯定的工夫给利用设置下TopMost,该计划也是可行的:
/// <summary>/// 计划二:循环置顶/// </summary>/// <returns></returns>private async Task SetTopMostLoop(){ while (true) { await Task.Delay(2000); var interopHelper = new WindowInteropHelper(this); Win32Api.SetWindowPos(interopHelper.Handle, Win32Api.HWND_TOPMOST, 0, 0, 0, 0, Win32Api.TOPMOST_FLAGS); }}
计划三:应用钩子
思考一下,其实大部分状况下,应用鼠标或键盘等其它输出设施才会导致窗口的置顶被抢,因而能够应用全局钩子捕捉输出事件,而后进行解决。
该计划是存在瑕疵的,因为存在不应用输出设施关上某个利用的状况,这种状况下置顶成果就会被新关上的置顶利用抢占。
// 计划三:当鼠标按下时置顶(仅思考了鼠标)private void MouseHook_OnMouseActivity(object sender, System.Windows.Forms.MouseEventArgs e){ Console.WriteLine("mouse down......"); _ = SetTopMostLater();}private MouseHook _mouseHook;
最初,本文是我对该问题想到的一些解决方案,Windows零碎的工作管理器能够运行在所有利用的最上层,兴许微软正是思考到上文提到的伪命题,因而没有凋谢该接口吧,理解原理的小伙伴欢送探讨。
本文三种计划的残缺demo见GitHub,能够参考的链接(对于该话题的探讨较老了):链接一、链接二。