Win32Api -- 使应用Always on top的几种方法
本文介绍几种使应用一直置于顶层的方法。
问题描述
一般情况下,想要将应用置于顶层,设置其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,可以参考的链接(关于该话题的讨论较老了):链接一、链接二。
Win32Api -- 使应用Always on top的几种方法的更多相关文章
- Duilib改进窗口拖动,使整个窗口都能拖动两种方法(转载)
转载:http://www.cnblogs.com/XiHua/articles/3490490.html 转载:http://blog.csdn.net/lostspeed/article/deta ...
- java使double保留两位小数的多方法 java保留两位小数
这篇文章主要介绍了java使double类型保留两位小数的方法,大家参考使用吧 复制代码 代码如下: mport java.text.DecimalFormat; DecimalFormat d ...
- F - Goldbach`s Conjecture 对一个大于2的偶数n,找有多少种方法使两个素数的和为n;保证素数a<=b; a+b==n; a,b都为素数。
/** 题目:F - Goldbach`s Conjecture 链接:https://vjudge.net/contest/154246#problem/F 题意:对一个大于2的偶数n,找有多少种方 ...
- 在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法。
在vc6.0下编的对话框界面如果没做过其他处理,往往显的很生硬,怎么样才能使他有Windows XP的风格呢,其实也很简单,我们来看看下面两种方法. 方法一: 1.首先确认你在Windows ...
- java使double保留两位小数的多方法
java使double保留两位小数的多方法 java保留两位小数 mport java.text.DecimalFormat; DecimalFormat df = new DecimalFormat ...
- 使WordPress改域名后网站正常运行的方法
使WordPress改域名后网站正常运行的方法 wp-content/wp-config.php $path = '/blog'; $scheme = (isset($_SERVER['HTTPS'] ...
- Select Top在七种数据库中的使用方法(包含mysql)
1. Oracle数据库 SELECT * FROM TABLE1 WHERE ROWNUM<=N 2. Infomix数据库 SELECT FIRST N * FROM TABLE1 3. D ...
- 分页查询的两种方法(双top 双order 和 row_number() over ())
--跳过10条取2条 也叫分页select top 2 * from studentwhere studentno not in (select top 2 studentno from studen ...
- access数据库 top语句失效解决方法
使用查询语句 select top 1 * from News order by [PublicTime] desc 就不一定管用了,如果News表里面的PublicTime字段 ...
随机推荐
- SpringBoot中获取上下文
在实际开发中,有时候会根据某个bean的名称或class到Spring容器中获取对应的Bean.这里只做个简单的记录,方便后续自查. @Component public class SpringCon ...
- JAVA并发(2)-ReentrantLock的见解
上节,我们讲了AQS的阻塞与释放实现原理,线程间通信(Condition)的原理.这次,我们就讲讲基于AQS实现的ReentrantLock(重入锁). 1. 介绍 结合上面的ReentrantLoc ...
- [c++] 分号的使用
加分号的情况: 语句结束加分号(否则编译器不知道在哪里结束语句,编译器不识别换行,写代码时换行和退格只是为了看着舒服,但本质上代码是写给编译器看的) 声明语句后加分号(也是一种语句) 结构体.类定义后 ...
- QT相关书籍
文章转载自:http://www.cctry.com/thread-290005-1-1.html 最近一段时间,陆陆续续给大家更新了不少基于Qt开发的不错的书籍,可以说每本都不错.不过放在这一堆大家 ...
- Linux_进程管理的基本概述
一.进程的基本概述 1️⃣:进程是已启动的可执行程序的运行中实例 2️⃣:/proc目录下以数字为名的目录,每一个目录代表一个进程,保存着进程的属性信息 3️⃣:每一个进程的PID是唯一的,就算进程退 ...
- 『言善信』Fiddler工具 — 2、HTTP请求内容详解
目录 1.HTTP协议介绍 2.使用Fiddler抓取一个请求 3.НТТP请求报文 (1)НТТP请求报文说明 (2)请求行 (3)请求头(Request Header) (4)请求体 4.НТТР ...
- TPS和响应时间之间是什么关系
在这个图中,定义了三条曲线.三个区域.两个点以及三个状态描述. 三条曲线:吞吐量的曲线(紫色).使用率 / 用户数曲线(绿色).响应时间曲线(深蓝色).三个区域:轻负载区(Light Load).重负 ...
- MongoDB学习笔记:MongoDB 数据库的命名、设计规范
MongoDB学习笔记:MongoDB 数据库的命名.设计规范 第一部分,我们先说命名规范. 文档 设计约束 UTF-8 字符 不能包含 \0 字符(空字符),这个字符标识建的结尾 . 和 $ ...
- TVM量化小结手册
TVM量化小结手册 文章目录 Offical References TVM quantization roadmap INT8 quantization proposal Quantization S ...
- NeuWare软件开发环境
NeuWare软件开发环境 NeuWare 全面支持各类主流编程框架(如TensorFlow,Caffe,Caffe2,MXNet和ONNX等).用户可面向上述编程框架,便捷地在MLU100上开发和部 ...