【发布时间】:2016-03-24 16:14:42
【问题描述】:
我想要一个提供Alt + Tab 类似功能的工具,但我不想在所有打开的窗口之间切换,而是想将它们缩小到仅 1 个特定程序(例如 firefox.exe)。
我能想到的只是使用GetWindowText 来获取标题中包含“Mozilla Firefox”的窗口列表,然后使用ShowWindowAsync 来显示它们,但如果有的话似乎效果不佳其他打开的窗口的标题中也有“Mozilla Firefox”这句话。
有没有更好的解决方案? 代码如下:
/// <summary>Contains functionality to get all the open windows.</summary>
public static class OpenWindowGetter
{
/// <summary>Returns a dictionary that contains the handle and title of all the open windows.</summary>
/// <returns>A dictionary that contains the handle and title of all the open windows.</returns>
public static IDictionary<HWND, string> GetOpenWindows()
{
HWND shellWindow = GetShellWindow();
Dictionary<HWND, string> windows = new Dictionary<HWND, string>();
EnumWindows(delegate(HWND hWnd, int lParam)
{
if (hWnd == shellWindow) return true;
if (!IsWindowVisible(hWnd)) return true;
int length = GetWindowTextLength(hWnd);
if (length == 0) return true;
StringBuilder builder = new StringBuilder(length);
GetWindowText(hWnd, builder, length + 1);
windows[hWnd] = builder.ToString();
return true;
}, 0);
return windows;
}
private delegate bool EnumWindowsProc(HWND hWnd, int lParam);
[DllImport("USER32.DLL")]
private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);
[DllImport("USER32.DLL")]
private static extern int GetWindowText(HWND hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("USER32.DLL")]
private static extern int GetWindowTextLength(HWND hWnd);
[DllImport("USER32.DLL")]
private static extern bool IsWindowVisible(HWND hWnd);
[DllImport("USER32.DLL")]
private static extern IntPtr GetShellWindow();
}
我就是这样使用它的:
/// <summary>
/// Get a window handle by a title
/// </summary>
/// <param name="windowTitle"></param>
/// <param name="wildCard">match if window title contains input windowTitle</param>
/// <returns></returns>
public static int GetWindowHandle(string windowTitle, bool wildCard = false)
{
var processList = OpenWindowGetter.GetOpenWindows();
foreach (var process in processList)
{
if ((wildCard && process.Value.ToLower().Contains(windowTitle.ToLower())) //Find window by wildcard
|| !wildCard && process.Value.Equals(windowTitle)) //Find window with exact name
{
int a = (int)process.Key;
return a;
}
}
return 0;
}
【问题讨论】:
-
一个应用程序的不同(顶级)窗口通常共享同一个窗口类。在您的
EnumWindowProc回调中调用 GetClassName 以过滤类名。 -
只有您可以决定您的标准。这些是什么?决定后,使用 EnumWindows 获取顶级窗口