C#winform-获取外部程序子进程的位置和大小

时间:2018-09-27 22:34:37

标签: c# winforms c#-4.0 c#-3.0

1个月的网上狩猎后,我没有找到解决问题的方法。现在,我觉得该发布这个帖子了。

我的项目:它在任务栏中找到外部正在运行的软件,并获取窗口的位置,名称,进程ID和标题并将其保存在datagrid中。我在Windows 7的Winform中使用C#

问题:我的代码可以找到正在运行的软件的process(processID)并可以获取的大小和其他详细信息。但是问题是我的代码无法找到子/子窗口的大小或其他任何细节。

示例信息:我附上了有效的示例图像和代码,没有任何错误。但不捕获运行子窗口的其他程序。 在图像中,您可以看到Webex软件可以找到子窗口并在其上附加一个弹出框(仅作为示例,它可能找到子窗口)
在第二张图片中,您可以看到我的代码只能找到skype(lync)的主窗口

任何建议或方向都会有很大帮助,谢谢

导入dll

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindow(string strClassName, string strWindowName);

    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle);
    public struct Rect
    {
        public int Left { get; set; }
        public int Top { get; set; }
        public int Right { get; set; }
        public int Bottom { get; set; }
    }

    [DllImport("user32.dll")]
    static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

运行代码,按一下按钮即可找到窗口和尺寸,并对w和h进行一些计算。

        Process[] processes = Process.GetProcesses();
        foreach (Process p in processes)
        {
            if ((int)p.MainWindowHandle != 0)
            {

                if (!String.IsNullOrEmpty(p.MainWindowTitle))
                {

                    myCurrentProcessName = p.ProcessName;
                    //listBox1.Items.Add(p.MainWindowTitle); // add all process to listbox

                    //find windows size and location
                    IntPtr ptr = p.MainWindowHandle;
                    Rect appRect = new Rect();
                    GetWindowRect(ptr, ref appRect);

                    x = appRect.Left;
                    y = appRect.Top;
                    r = appRect.Right;
                    b = appRect.Bottom;
                    //
                    //calculate size of the app
                    w = r - x;
                    h = b - y;
                    dataGridView1.Rows.Add(p.Id, p.MainWindowHandle, p.ProcessName, p.MainWindowTitle, IsIconic(wHnd), appState, x, y, w, h);
                 }
           }
         }

Skype child conversation windows capture result shows main windows location only

更新:按照Abye的建议。我试图用谷歌EnumChildWindows。我从此链接How can I get the child windows of a window given its HWND?中找到了一个代码,我试图在我的代码中实现它,但是dnt知道如何使用它并获取子窗口的位置和大小。

private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);

    [DllImport("user32")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);

    private IntPtr _MainHandle;

    public Form1(IntPtr handle)
    {
        this._MainHandle = handle;
    }

    public List<IntPtr> GetAllChildHandles()
    {
        List<IntPtr> childHandles = new List<IntPtr>();

        GCHandle gcChildhandlesList = GCHandle.Alloc(childHandles);
        IntPtr pointerChildHandlesList = GCHandle.ToIntPtr(gcChildhandlesList);

        try
        {
            EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
            EnumChildWindows(this._MainHandle, childProc, pointerChildHandlesList);
        }
        finally
        {
            gcChildhandlesList.Free();
        }

        return childHandles;
    }

    private bool EnumWindow(IntPtr hWnd, IntPtr lParam)
    {
        GCHandle gcChildhandlesList = GCHandle.FromIntPtr(lParam);

        if (gcChildhandlesList == null || gcChildhandlesList.Target == null)
        {
            return false;
        }

        List<IntPtr> childHandles = gcChildhandlesList.Target as List<IntPtr>;
        childHandles.Add(hWnd);

        return true;
    }


 private void button5_Click(object sender, EventArgs e)
    {
     Process[] anotherApps = Process.GetProcessesByName(textBox1.Text);
        if (anotherApps.Length == 0) return;
        if (anotherApps[0] != null)
        {
            var allChildWindows = new Form1(anotherApps[0].MainWindowHandle).GetAllChildHandles();
         }
     }

这是GetAllChildHandles()代码的返回值,但是如何使用它来获取子窗口的位置和大小?

enter image description here

enter image description here

0 个答案:

没有答案