我希望有一个提供类似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;
}
答案 0 :(得分:1)
可以使用System.Diagnostics.Process.GetProcessesByName()
方法搜索进程。您可以在此处获取有关该功能的更多详细信息:https://msdn.microsoft.com/en-us/library/z3w4xdc9(v=vs.110).aspx
下面的函数接受进程的名称,例如&#34; firefox.exe&#34;并返回具有窗口的第一个匹配过程的主窗口的Window句柄 (进程可以在没有主窗口的情况下运行,如服务或控制台应用程序等...... )
public static IntPtr GetMainWindowHandle(string ProcessName)
{
Process[] ProcessList = Process.GetProcessesByName(ProcessName);
foreach (Process ThisProcess in ProcessList)
{
if (ThisProcess.MainWindowHandle != IntPtr.Zero)
{
return ThisProcess.MainWindowHandle;
}
}
return IntPtr.Zero;
}
可能已经打开了同一进程的多个实例,因此您可能希望更直接地使用生成的ProcessList。此外,Process类中内置了许多函数,您可能会发现它们很有用。
更新(根据您的评论问题):
所有Chrome进程都不等于其他Chrome标签。
相反,每个Chrome进程实际上都是一个单独的Web应用程序,插件或Tab处理引擎
谷歌将每个网络应用程序,插件和标签后台进程分成他们自己的Windows进程,以便在插件崩溃时保护主进程。
这可以防止崩溃的插件影响主Chrome应用程序或任何其他选项卡
此外,它还可以让操作系统管理并行多任务处理
您可以通过点击&#34; Shift-ESC&#34;在Chrome任务管理器中查看每个内容。在Chrome中。
您可以在此处详细了解:http://blog.chromium.org/2008/09/multi-process-architecture.html
Chrome将其所在的父进程中的每个标签窗口作为单独的顶级窗口进行管理。 通过查看所有WINDOWS,您最初的想法是最好的解决方案,而不是查看所有过程。 通过在下面的示例中调用SwitchToAllChromeWinows(),它遍历所有窗口并切换到任何具有文本&#34; Google Chrome&#34; 但是,可能有其他窗口在其标题中包含该文本。 此外,这会切换到所有这些并将它们全部聚焦到一个一个焦点。 如果您正在寻找特定的搜索字符串,则可以将搜索字符串限制为更具体。
public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll")]
protected static extern bool EnumWindows(Win32Callback enumProc, IntPtr lParam);
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
List<IntPtr> pointers = GCHandle.FromIntPtr(pointer).Target as List<IntPtr>;
pointers.Add(handle);
return true;
}
private static List<IntPtr> GetAllWindows()
{
Win32Callback enumCallback = new Win32Callback(EnumWindow);
List<IntPtr> AllWindowPtrs = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(AllWindowPtrs);
try
{
EnumWindows(enumCallback, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return AllWindowPtrs;
}
[DllImport("User32", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetWindowText(IntPtr windowHandle, StringBuilder stringBuilder, int nMaxCount);
[DllImport("user32.dll", EntryPoint = "GetWindowTextLength", SetLastError = true)]
internal static extern int GetWindowTextLength(IntPtr hwnd);
private static string GetTitle(IntPtr handle)
{
int length = GetWindowTextLength(handle);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(handle, sb, sb.Capacity);
return sb.ToString();
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
private static void SwitchToAllChromeWinows()
{
List<IntPtr> AllWindowsPtrs = GetAllWindows();
foreach (IntPtr ThisWindowPtr in AllWindowsPtrs)
{
if (GetTitle(ThisWindowPtr).Contains("Google Chrome") == true)
{
SwitchToThisWindow(ThisWindowPtr, true);
}
}
}
<强>更新强>
如果您只使用Chrome或想要更直接的方式,那么您可以使用Google的Chrome API来直接管理标签:
http://code.google.com/chrome/extensions/windows.html#method-getAll
http://code.google.com/chrome/extensions/tabs.html#method-getAllInWindow
答案 1 :(得分:0)
这就是为我做的事情:
[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool IsWindowVisible(int hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int GetWindowText(int hWnd, StringBuilder title, int size);
delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
public List<IntPtr> GetMainWindowHandle()
{
var list = Process.GetProcessesByName(ProcessName);
List<IntPtr> windowList = new List<IntPtr>();
foreach (Process process in list)
{
if (process.MainWindowHandle != IntPtr.Zero)
//windowList.Add(ThisProcess.MainWindowHandle);
{
foreach (ProcessThread processThread in process.Threads)
{
EnumThreadWindows(processThread.Id,
(hWnd, lParam) =>
{
//Check if Window is Visible or not.
if (!IsWindowVisible((int)hWnd))
return true;
//Get the Window's Title.
StringBuilder title = new StringBuilder(256);
GetWindowText((int)hWnd, title, 256);
//Check if Window has Title.
if (title.Length == 0)
return true;
windowList.Add(hWnd);
return true;
}, IntPtr.Zero);
}
}
}
return windowList;
}