我正在开发一个WPF应用程序,我需要一种方法来获取应用程序中的所有打开的窗口,包括从另一个线程打开的窗口。我试过了Application.Current.Windows
,但这并没有给我从另一个线程打开的窗口。甚至可以访问另一个线程打开的窗口?不应该所有窗口都在同一个应用程序域中吗?
感谢。
答案 0 :(得分:7)
这应该这样做。它将返回给定应用程序名称的每个打开窗口的整数指针列表:
public delegate bool Win32Callback(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr parentHandle, Win32Callback callback, IntPtr lParam);
static void Main(string[] args)
{
Process[] processes = Process.GetProcessesByName("MyApp");
var windows = new List<IntPtr>();
foreach (Process p in processes)
{
IEnumerable<IntPtr> w = GetRootWindowsOfProcess(p.Id);
windows.AddRange(w);
}
}
private static IEnumerable<IntPtr> GetRootWindowsOfProcess(int pid)
{
IEnumerable<IntPtr> rootWindows = GetChildWindows(IntPtr.Zero);
var dsProcRootWindows = new List<IntPtr>();
foreach (IntPtr hWnd in rootWindows)
{
uint lpdwProcessId;
GetWindowThreadProcessId(hWnd, out lpdwProcessId);
if (lpdwProcessId == pid)
dsProcRootWindows.Add(hWnd);
}
return dsProcRootWindows;
}
private static IEnumerable<IntPtr> GetChildWindows(IntPtr parent)
{
var result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
var childProc = new Win32Callback(EnumWindow);
EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally
{
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer)
{
GCHandle gch = GCHandle.FromIntPtr(pointer);
var list = gch.Target as List<IntPtr>;
if (list == null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(handle);
// You can modify this to check to see if you want to cancel the operation, then return a null here
return true;
}
现在作为评论者之一,您不应该有多个线程在进行GUI工作。一个线程应该进行GUI绘图,而其他线程执行实际的其他工作。
答案 1 :(得分:3)
Window
类检查当前应用程序的调度程序是当前线程的调度程序,如果是,则将其添加到Windows
集合中。看起来这些其他窗口在公共集合中不公开,但Application
,NonAppWindowsInternal
上有一个具有窗口的内部属性。
我总是在单个UI线程上创建UI对象。如果这样做,您将可以通过Application.Current.Windows
访问所有Window对象。
答案 2 :(得分:1)
我不确定这个解决方案,但我发现它最接近一个。
尝试获取程序:
using System.Diagnostics;
Process[] processlist = Process.GetProcesses();
foreach (Process process in processlist)
{
if (!String.IsNullOrEmpty(process.MainWindowTitle))
{
Console.WriteLine("Process: {0} ID: {1} Window title: {2}", process.ProcessName, process.Id, process.MainWindowTitle);
}
}
如果这没有帮助,请尝试使用Process.GetProcessesByName(“ApplicationName”)并查看它返回的内容。
查看this solution和MSDN class page以及其中的可用方法也可能有所帮助。