在 WPF 中,如果想要使用代码控制,让某个窗口作为当前用户的输入的逻辑焦点的窗口,也就是在当前用户活动的窗口的最上层窗口,默认使用 Activate 方法,通过这个方法在大部分设备都可以做到激活窗口

但是在一些特殊的设备上,使用下面代码调起窗口只是在任务栏闪烁图标,而没有让窗口放在最上层

window.Show();
window.Activate();

在大部分设备上,通过 Show 和 Activate 组合可以让窗口作为当前用户活动的,即使窗口之前是最小化或隐藏,都可以通过 Show 的方法显示

但是某些设备窗口被盖在其他的窗口的下面,此时的窗口的 window.IsActive 还是 true 但是调用 Activate 不会让窗口放在上层

我在网上看到好多小伙伴调用了 SetForegroundWindow 方法,其实现在 WPF 是开源的,可以看到 Window 的 Activate 方法是这样写

        public bool Activate()
{
// this call ends up throwing an exception if Activate
// is not allowed
VerifyApiSupported();
VerifyContextAndObjectState();
VerifyHwndCreateShowState(); // Adding check for IsCompositionTargetInvalid
if (IsSourceWindowNull || IsCompositionTargetInvalid)
{
return false;
} return UnsafeNativeMethods.SetForegroundWindow(new HandleRef(null, CriticalHandle));
}

源代码请看 github

也就是调用 SetForegroundWindow 和调用 Activate 方法是差不多的,如果调用 Activate 应该调用 SetForegroundWindow 也差不多

通过大佬的 SetForegroundWindow的正确用法 - 子坞 - 博客园 可以了解到,需要按照以下步骤

    1.得到窗口句柄FindWindow
    2.切换键盘输入焦点AttachThreadInput
    3.显示窗口ShowWindow(有些窗口被最小化/隐藏了)
    4.更改窗口的Zorder,SetWindowPos使之最上,为了不影响后续窗口的Zorder,改完之后,再还原
    5.最后SetForegroundWindow

在 WPF 中对应的更改窗口的顺序使用的是 Topmost 属性,同时设置顺序需要做一定小的更改

在 WPF 中通过 c# - Bring a window to the front in WPF - Stack Overflow 可以了解到如何用 AttachThreadInput 方法

整个代码请看下面,具体的 win32 方法我就没有写出来了,请小伙伴自己添加

        private static void SetWindowToForegroundWithAttachThreadInput(Window window)
{
var interopHelper = new WindowInteropHelper(window);
var thisWindowThreadId = Win32.User32.GetWindowThreadProcessId(interopHelper.Handle, IntPtr.Zero);
var currentForegroundWindow = Win32.User32.GetForegroundWindow();
var currentForegroundWindowThreadId = Win32.User32.GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero); // [c# - Bring a window to the front in WPF - Stack Overflow](https://stackoverflow.com/questions/257587/bring-a-window-to-the-front-in-wpf )
// [SetForegroundWindow的正确用法 - 子坞 - 博客园](https://www.cnblogs.com/ziwuge/archive/2012/01/06/2315342.html )
/*
  1.得到窗口句柄FindWindow
    2.切换键盘输入焦点AttachThreadInput
    3.显示窗口ShowWindow(有些窗口被最小化/隐藏了)
    4.更改窗口的Zorder,SetWindowPos使之最上,为了不影响后续窗口的Zorder,改完之后,再还原
    5.最后SetForegroundWindow
*/
Win32.User32.AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true); window.Show();
window.Activate();
// 去掉和其他线程的输入链接
Win32.User32.AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false); // 用于踢掉其他的在上层的窗口
window.Topmost = true;
window.Topmost = false;

我测试了几个原本没有让窗口放在上层的设备,使用上面的代码可以设置,但是我不了解设置上面代码可能的坑是什么

附带 walterlv 的测试工具,可以用来拿到当前的 GetForegroundWindow 是哪个

walterlv 的工具

另外少君小伙伴写了一个有趣的库,里面封装了很多 win32 的方法,请看 kkwpsv lsjutil

WPF 让窗口激活作为前台最上层窗口的方法的更多相关文章

  1. 将后台窗口激活到前台的方法(使用AttachThreadInput和SetForegroundWindow两个API)

    下面这种方法是我见到的最理想的,还有一些其他的方法,像通过SetWindowsPos这个API设置窗口的Z-oder到最顶层,再设置回去.还有通过把当前窗口设置到底层,然后激活目标窗口等等方法. HW ...

  2. js设置当前窗口为最上层窗口

    实际使用iframe框架时会遇到当前窗口页面不能位于最上层窗口的情况,或者是防止自己的网站被别人放在他们的iframe中,这时就需要设置: <script language="java ...

  3. WPF的消息机制(三)- WPF内部的5个窗口之处理激活和关闭的消息窗口以及系统资源通知窗口

    原文:WPF的消息机制(三)- WPF内部的5个窗口之处理激活和关闭的消息窗口以及系统资源通知窗口 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/p ...

  4. WPF中禁止WebBrowser控件打开新窗口

    一.针对纯WPF的WebBrowser控件: <summary> Suppress Script Errors In WPF WebBrowser </summary> pub ...

  5. Win32 程序在启动时激活前一个启动程序的窗口

    UWP 程序天生单实例.当然,新 API (10.0.17134)开始也提供了多实例功能.不过,传统 Win32 程序可就要自己来控制单实例了. 本文介绍简单的几个 Win32 方法调用,使 Win3 ...

  6. WPF DispatcherTimer(定时器应用) 无人触摸60s自动关闭窗口

    原文:WPF DispatcherTimer(定时器应用) 无人触摸60s自动关闭窗口 如果无人触摸:60s自动关闭窗口 xmal:部分 <s:SurfaceWindow x:Class=&qu ...

  7. WPF 判断一个对象是否是设计时的窗口类型,而不是运行时的窗口

    原文:WPF 判断一个对象是否是设计时的窗口类型,而不是运行时的窗口 当我们对 Window 类型写一个附加属性的时候,在属性变更通知中我们需要判断依赖对象是否是一个窗口.但是,如果直接判断是否是 W ...

  8. C# 禁用窗口激活

    如果界面点击时,不想让窗口激活,可以按如下操作: 1 public MainWindow() 2 { 3 InitializeComponent(); 4 SourceInitialized += O ...

  9. C# 获取指定窗口的上层窗口

    如何获取当前窗口层级上方的所有窗口信息 User32有函数GetWindow function (winuser.h) - Win32 apps | Microsoft Docs,可以根据已知窗口句柄 ...

  10. WPF编程,C#中对话框自动关闭的一种方法。

    原文:WPF编程,C#中对话框自动关闭的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/details/8 ...

随机推荐

  1. 记录--Js基础练习题目

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1.使用js,在页面中打印以下图案 提示: document.write可以在页面中打印内容<br>在html中代表换行, 在 ...

  2. 记录--前端加载超大图片(100M以上)实现秒开解决方案

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 前端加载超大图片时,一般可以采取以下措施实现加速: 图片压缩:将图片进行压缩可以大幅减小图片的大小,从而缩短加载时间.压缩图片时需要 ...

  3. Redis无法向磁盘写入RBD数据

    2020-12-09 11:52:25|21965|ERROR|storage/DRedisAsyncCallback.cpp:394[cbIncrby]Cmd 'INCRBY' failed, ke ...

  4. MySQL函数GROUP_CONCAT()函数简介

    一.数据需求按id分组然后把name用英文逗号分隔开 id name countryid age 1 曹操 1 56 2 刘备 2 47 3 孙权 3 38 4 司马懿 1 61 5 诸葛亮 2 42 ...

  5. 探寻UUID的起源与奥秘:从时间戳到唯一标识

    1. UUID起源与原理 UUID(Universally Unique Identifier)是一种唯一标识符,最初由Apollo计算机公司的软件工程师Roedy Green在1987年提出.其原理 ...

  6. 没有Python基础,如何学习用Python写机器学习

    前言 我是一个完全没用过python的人,所以,想写机器学习,就得从语法入手. 首先上W3cSchool去学习基础语法. 基础语法都差不多,重点看一下函数,模块,面向对象. 函数的写法稍有不同,格式上 ...

  7. OpenCvSharp+Yolov5Net+Onnx 完整Demo

    效果 工程 代码 using Microsoft.ML.OnnxRuntime; using OpenCvSharp; using System; using System.Collections.G ...

  8. JAVA10进制数转45进制

    import java.util.HashMap; public class test2 { // 定义45进制数字 private static final String X45 = "0 ...

  9. Collation 差异导致 KingbaseES 与 Oracle 查询结果不同

    问题引入 前端提了个问题,说是KingbaseES 返回的结果与 Oracle 返回的结果不一样.具体问题如下: oracle 执行结果:oracle 有结果返回. SQL> create ta ...

  10. 7 CSS选择器优先级

    7 选择器优先级 所谓CSS优先级,即是指CSS样式在浏览器中被解析的先后顺序.样式表中的特殊性描述了不同规则的相对权重. /* !important > 行内样式>ID选择器 > ...