在 Windows 8 上设置前景窗口

Posted

技术标签:

【中文标题】在 Windows 8 上设置前景窗口【英文标题】:Set foreground window on Windows 8 【发布时间】:2013-06-26 14:16:37 【问题描述】:

我已经阅读了一些使用 C# 强制窗口显示在前台的方法,利用 Win32 的 user32.dll。

How do I bring an unmanaged application window to front, and make it the active window for (simulated) user input https://shlomio.wordpress.com/2012/09/04/solved-setforegroundwindow-win32-api-not-always-works/

除了一种情况外,这些都可以正常工作。 在 Windows 8 上,如果“开始”菜单或 Windows 应用商店应用程序在前台,这些都将失败。

不过,我只需要在“开始”菜单位于前台时进行这项工作。 有没有隐藏的方法来做到这一点?

【问题讨论】:

我可能错了,但我相信您可以使用msdn.microsoft.com/en-us/library/windows/desktop/… 完成此操作。问题是搜索窗口已经位于最顶层,因此您需要获取该窗口的句柄并将其更改为 zOrder,然后使用相同的函数将您的窗口也设置为最顶层。 我自己没有尝试过,但我遇到了一些报告说它没有:***.com/questions/15850230/… 我也无法尝试,因为我没有 Windows 8,但您需要了解的是,所有 Windows 8 窗口最终都是使用 GDI 构建的,它们具有正常的句柄,您可以像以前一样使用Win32功能,所以我相信值得你尝试。 【参考方案1】:
            DispatcherHelper.CheckBeginInvokeOnUI(async () =>
            
                try
                  
                    if (!this.IsActive)
                    
                        //pressing windows button
                        InputSimulator.SimulateKeyPress(VirtualKeyCode.LWIN);
                    
                    await Task.Delay(1000);

                    ApplicationRunningHelper.GetCurrentProcessOnFocus();
                
                catch (Exception ex)
                
                 ...
                
            );

 public static class ApplicationRunningHelper
    
        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("user32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

        [DllImport("user32.dll")]
        private static extern bool IsIconic(IntPtr hWnd);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        // When you don't want the ProcessId, use this overload and pass 
        // IntPtr.Zero for the second parameter
        [DllImport("user32.dll")]
        public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

        [DllImport("kernel32.dll")]
        public static extern uint GetCurrentThreadId();

        /// The GetForegroundWindow function returns a handle to the 
        /// foreground window.
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool BringWindowToTop(IntPtr hWnd);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool BringWindowToTop(HandleRef hWnd);

        [DllImport("user32.dll")]
        public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);

        //one source
        private static int SW_HIDE = 0;
        private static int SW_SHOWNORMAL = 1;
        private static int SW_SHOWMINIMIZED = 2;
        private static int SW_SHOWMAXIMIZED = 3;
        private static int SW_SHOWNOACTIVATE = 4;
        private static int SW_RESTORE = 9;
        private static int SW_SHOWDEFAULT = 10;

        //other source
        private static int SW_SHOW = 5;

        /// <summary>
        /// check if current process already running. if runnung, set focus to 
        /// existing process and returns true otherwise returns false.
        /// </summary>
        /// <returns></returns>
        public static bool GetCurrentProcessOnFocus()
        
            try
            
                Process me = Process.GetCurrentProcess();
                Process[] arrProcesses = Process.GetProcessesByName(me.ProcessName);
                IntPtr hWnd = arrProcesses[0].MainWindowHandle;
                ForceForegroundWindow(hWnd);
                return true;
            
            catch (Exception)
            
                return false;
            
        

        public static void ForceForegroundWindow(IntPtr hWnd)
        
            uint foreThread = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
            uint appThread = GetCurrentThreadId();
            const uint SW_SHOW = 5;

            if (foreThread != appThread)
            
                AttachThreadInput(foreThread, appThread, true);
                BringWindowToTop(hWnd);
                ShowWindow(hWnd, SW_SHOW);
                AttachThreadInput(foreThread, appThread, false);
            
            else
            
                BringWindowToTop(hWnd);
                ShowWindow(hWnd, SW_SHOW);
            
        
    

【讨论】:

以上是关于在 Windows 8 上设置前景窗口的主要内容,如果未能解决你的问题,请参考以下文章

Windows 8 控制台任务命令窗口

Windows2008系统基本设置

Win32 应用程序是不是也可以在 Windows 7 和 Windows 8/8.1 上运行?

前景与活动窗口

Windows 8的语音识别

在桌面上为 Windows 10 UWP 应用设置窗口大小