加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 获取所有打开的窗口

发布时间:2020-12-15 23:45:29 所属栏目:百科 来源:网络整理
导读:我正在研究 WPF应用程序,我需要一种方法来获取应用程序中的所有打开的窗口,包括从另一个线程打开的窗口.我尝试过Application.Current. Windows,但这并没有给我从另一个线程打开的窗口.甚至可以访问另一个线程打开的窗口?不应该所有窗口都在同一个应用程序域
我正在研究 WPF应用程序,我需要一种方法来获取应用程序中的所有打开的窗口,包括从另一个线程打开的窗口.我尝试过Application.Current. Windows,但这并没有给我从另一个线程打开的窗口.甚至可以访问另一个线程打开的窗口?不应该所有窗口都在同一个应用程序域中吗?

谢谢.

解决方法

这应该做到这一点.它将返回给定应用程序名称的每个打开窗口的整数指针列表:

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绘图,而其他线程执行实际的其他工作.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读