简体   繁体   English

当MainWindowHandle为0时将窗口置于前台

[英]Bring Window To Foreground When MainWindowHandle Is 0

The following code brings the window to the foreground, if the MainWindowHandle is not 0. 如果MainWindowHandle不为0,则以下代码将窗口置于前台。

How can I bring a window to the front that has MainWindowHandle = 0? 如何将具有MainWindowHandle = 0的窗口置于最前面?

This is for the Microsoft Excel - Compatibility Checker window that shows a GUI but does not have an icon in the task bar and has MainWindowHandle = 0. 这用于Microsoft Excel-兼容性检查器窗口,该窗口显示GUI,但任务栏中没有图标,并且MainWindowHandle = 0。

I have no other instances of Excel running. 我没有其他正在运行的Excel实例。

Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Tricks {
     [DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool SetForegroundWindow(IntPtr hWnd);
  }
"@

$excel = (Get-Process | Where-Object { $_.ProcessName -eq 'EXCEL' }).MainWindowHandle
[void] [Tricks]::SetForegroundWindow($excel)

In Windows Task Manager, I can right click on 'Microsoft Excel - Compatibility Checker' and click on "Bring To Front" and that works. 在Windows Task Manager中,我可以右键单击“ Microsoft Excel-Compatibility Checker”,然后单击“ Bring To Front”,它可以正常工作。 How can I mimic this functionality in Powershell? 如何在Powershell中模仿此功能?

Thanks to IInspectable for pointing me in the right direction. 感谢IInspectable为我指出正确的方向。

This code gets the real MainWindowHandle value: 此代码获取真实的MainWindowHandle值:

$TypeDef2 = @"

using System;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Api
{

public class WinStruct
{
   public string WinTitle {get; set; }
   public int MainWindowHandle { get; set; }
}

public class ApiDef
{
   private delegate bool CallBackPtr(int hwnd, int lParam);
   private static CallBackPtr callBackPtr = Callback;
   private static List<WinStruct> _WinStructList = new List<WinStruct>();

   [DllImport("User32.dll")]
   [return: MarshalAs(UnmanagedType.Bool)]
   private static extern bool EnumWindows(CallBackPtr lpEnumFunc, IntPtr lParam);

   [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
   static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

   private static bool Callback(int hWnd, int lparam)
   {
       StringBuilder sb = new StringBuilder(256);
       int res = GetWindowText((IntPtr)hWnd, sb, 256);
      _WinStructList.Add(new WinStruct { MainWindowHandle = hWnd, WinTitle = sb.ToString() });
       return true;
   }  

   public static List<WinStruct> GetWindows()
   {
      _WinStructList = new List<WinStruct>();
      EnumWindows(callBackPtr, IntPtr.Zero);
      return _WinStructList;
   }

}
}
"@

Add-Type -TypeDefinition $TypeDef2 -Language CSharpVersion3

$excelInstance = [Api.Apidef]::GetWindows() | Where-Object { $_.WinTitle.ToUpper() -eq "Microsoft Excel - Compatibility Checker".ToUpper() }

So now using this correct value, I can call the SetForegroundWindow() function: 因此,现在使用此正确值,我可以调用SetForegroundWindow()函数:

Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Tricks {
     [DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool SetForegroundWindow(IntPtr hWnd);
  }
"@
[void] [Tricks]::SetForegroundWindow($excelInstance.MainWindowHandle)

I wrote a detailed blog about this on my website . 我在我的网站上写了一个详细的博客。

I've put up a full example on GitHub of how to create an Excel file, edit it and run the above code in a different thread which you have to do because the Excel popup blocks the main thread. 我已经在GitHub上举了一个完整的示例,说明如何创建Excel文件,对其进行编辑并在不同的线程中运行上述代码,因为Excel弹出窗口会阻止主线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM