WPF 让窗口激活做为前台最上层窗口的方法

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

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

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

在大部分设备上,经过 Show 和 Activate 组合可让窗口做为当前用户活动的,即便窗口以前是最小化或隐藏,均可以经过 Show 的方法显示github

可是某些设备窗口被盖在其余的窗口的下面,此时的窗口的 window.IsActive 仍是 true 可是调用 Activate 不会让窗口放在上层c#

我在网上看到好多小伙伴调用了 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 也差很少this

经过大佬的 SetForegroundWindow的正确用法 - 子坞 - 博客园 能够了解到,须要按照如下步骤线程

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

在 WPF 中对应的更改窗口的顺序使用的是 Topmost 属性,同时设置顺序须要作必定小的更改code

在 WPF 中经过 c# - Bring a window to the front in WPF - Stack Overflow 能够了解到如何用 AttachThreadInput 方法htm

整个代码请看下面,具体的 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

相关文章
相关标签/搜索