需要通过p/invoke和findwindowex()查找子窗口的示例 [英] Need examples of finding child window through p/invoke and findwindowex()

查看:97
本文介绍了需要通过p/invoke和findwindowex()查找子窗口的示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经完成了一项工作,以弄清楚如何使我们在工作中使用的程序自动化(我主要是asp.net开发人员,但最近在这里戴着很多帽子).我已经学习了如何使用p/invoke和findwindow()查找主窗口,并且已经能够在下面的控制台应用程序代码中使用findwindowex()在主窗口中找到控件.我还不清楚如何找到其他模态窗口.我需要的窗口是第三个子窗口,我已经能够找到该页面的句柄及其父,子等(spy ++)...但是无法找到显示如何使用该句柄的示例.打开它并操纵该页面上的其他控件.

我有一本书-.NET测试自动化食谱-一种解决问题的方法-James D. McCaffrey-但它没有打开和操作子窗口-窗口及其控件/窗口的示例.我使用的最新代码可以找到主窗口,并只返回该页面的句柄.该书说:(FindWindowEx()的第二个参数是控件的句柄,并指示FindWindowEx()在何处开始搜索;搜索从下一个孩子开始
控件...通过将IntPtr.Zero指定为第二个参数,可以指示FindWindowEx()在主窗体窗口中搜索所有控件.因此,如何指示它在从该主窗口分支的子窗口中搜索控件窗口"?在此先感谢您的建议!这是我工作的最后一个代码:
-------------------------------------------------- ----------

I''ve have a work assignment to figure out how to automate a program we use at work (I''m an asp.net developer mostly, but am wearing many hats here lately). I''ve learned how to find the main window with p/invoke and findwindow() and have been able to find controls on the main window using findwindowex() in the console app code below. It''s not clear to me how one finds other modal windows. The window I need is the 3rd child in and I''ve been able to find the handle of that page and its parent, children, etc.(spy++)...but am unable to find an example showing how to use that handle to open it and manipulate other controls on that page.

I have the book - .NET Test Automation Recipes - A Problem-Solution Approach - James D. McCaffrey - but it has no examples of opening and manipulating child - windows and their controls/windows. The latest code I had working could locate the main window and give back the handles of that page only. The book says: "The second argument (of FindWindowEx()) is a handle to a control and directs FindWindowEx() where to begin searching; the search begins with the next child
control...By specifying IntPtr.Zero as the second argument, you instruct FindWindowEx() to search all controls on the main form window." So how do I instruct it to search controls in the child windows branching off of that ''main window''? Thanks in advance for your suggestions! Here''s the last code I had working:
------------------------------------------------------------

//  Finds Control Indexes – modular
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;

namespace Color_Console
{
    class Program
    {
        [DllImport("user32.dll", EntryPoint = "FindWindowEx",
        CharSet = CharSet.Auto)]
        static extern IntPtr FindWindowEx(IntPtr hwndParent,
        IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
        IntPtr mwh = IntPtr.Zero; // main window handle
        [DllImport("user32.dll", EntryPoint = "FindWindow",
        CharSet = CharSet.Auto)]
        static extern IntPtr FindWindow(string lpClassName,
        string lpWindowName);
        [STAThread]
        static void Main(string[] args)
        {
            try
            {
                /*
                // launch AUT; see Section 3.1
                try
                {
                    Console.WriteLine("\nLaunching application under test");
                    string path = "C:\\Program Files\\color-mixer.application";
                    //*** string path = "C:\\Documents and Settings\\All Users\\Desktop\\DDD Version 7i";
                    Process p = Process.Start(path);
                    if (p == null)
                        Console.WriteLine("Warning: process may already exist");
                    // run UI test scenario here
                    Console.WriteLine("\nDone");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Fatal error: " + ex.Message);
                }
                 */
                IntPtr mwh = IntPtr.Zero; // main window handle
                bool formFound = false;
                int attempts = 0;
                while (!formFound && attempts < 25)
                {
                    if (mwh == IntPtr.Zero)
                    {
                        Console.WriteLine("Form not yet found");
                        Thread.Sleep(100);
                        ++attempts;
                        // *** mwh = FindWindow(null, "Form1");
                        // *** mwh = FindWindow(null, "Manager...;);
                        mwh = FindWindow(null, "Manager...");
                    }
                    else
                    {
                        Console.WriteLine("Form has been found");
                        formFound = true;
                    }
                }
                if (mwh == IntPtr.Zero)
                    throw new Exception("Could not find main window");
                else
                    Console.WriteLine("Handle to main window is " + mwh);
                Console.WriteLine("\nDone");
/*
                // Finding Controls By Window Name
                Console.WriteLine("Finding handle to textBox1");
                IntPtr tb = FindWindowEx(mwh, IntPtr.Zero, null, "");
                if (tb == IntPtr.Zero)
                    throw new Exception("Unable to find textBox1");
                else
                    Console.WriteLine("Handle to textBox1 is " + tb);
                Console.WriteLine("Finding handle to button1");
                IntPtr butt = FindWindowEx(mwh, IntPtr.Zero, null, "button1");
                if (butt == IntPtr.Zero)
                    throw new Exception("Unable to find button1");
                else
                    Console.WriteLine("Handle to button1 is " + butt);
                // END Finding Controls By Window Name
*/
                // Finding Controls By Index
                Console.WriteLine("Finding handle to Index_1");
                IntPtr indx1 = FindWindowByIndex(mwh, 1);
                if (indx1 == IntPtr.Zero)
                    throw new Exception("Unable to find Index_1");
                else
                    Console.WriteLine("Handle to Index_1 is " + indx1);
                Console.WriteLine("Finding handle to Index_2");
                IntPtr indx2 = FindWindowByIndex(mwh, 2);
                if (indx2 == IntPtr.Zero)
                    throw new Exception("Unable to find Index_2");
                else
                    Console.WriteLine("Handle to Index_2 is " + indx2);
                Console.WriteLine("Finding handle to Index_3");
                IntPtr indx3 = FindWindowByIndex(mwh, 3);
                if (indx3 == IntPtr.Zero)
                    throw new Exception("Unable to find Index_3");
                else
                    Console.WriteLine("Handle to Index_3 is " + indx3);
                Console.WriteLine("Finding handle to Index_4");
                IntPtr indx4 = FindWindowByIndex(mwh, 4);
                if (indx4 == IntPtr.Zero)
                    throw new Exception("Unable to find Index_4");
                else
                    Console.WriteLine("Handle to Index_4 is " + indx4);
                // END Finding Controls By Index
            }
            catch (Exception ex)
            {
                Console.WriteLine("Fatal error: " + ex.Message);
            }
            Thread.Sleep(20100);
        }

        static IntPtr FindWindowByIndex(IntPtr hwndParent, int index)
        {
            if (index == 0)
                return hwndParent;
            else
            {
                int ct = 0;
                IntPtr result = IntPtr.Zero;
                do
                {
                    result = FindWindowEx(hwndParent, result, null, null);
                    if (result != IntPtr.Zero)
                        ++ct;
                } while (ct < index && result != IntPtr.Zero);
                return result;
            }
        }

    }
}

推荐答案

我能够通过嵌套类似于访问一级子级的代码的方式来完成内部子级窗口的查找和操作. .仅在下一个嵌套中使用在变量(即indx2)中以编程方式访问的句柄,如下所示:

IntPtr indxb1 = FindWindowByIndex(indx2,1);

请参阅下面的更完整的示例.我给人的印象是您在spy ++中看到的句柄号可以直接在代码中引用,但不能.显然,只能动态访问这些句柄,以使其保持在正确的win32数据类型(HWND/IntPtr(在C#中))中.

不幸的是,这种解决方案给我带来了一个新的问题,我将继续该问题并发表新的帖子,但这里会提到.我现在可以通过代码访问的窗口与我在spy ++中看到的窗口完全相同,但是此页面上还有许多其他控件未在spy ++中显示...我真的需要知道为什么.到目前为止,我无法通过使用FindWindowByIndex()或任何其他方式的代码来访问它们.我将发布这个新的其他软件.

解决方法如下:

I was able to accomplish finding and manipulating inner - child windows by nesting code similar to what I used to access the first level children...only the handle accessed programmatically in the variable (i.e. indx2) was used in the next nest as:

IntPtr indxb1 = FindWindowByIndex(indx2, 1);

See more complete example below. I was under the impression the handle numbers you see in spy++ could be referred to directly in code, but they cannot. The handles are apparently only accessible dynamically to keep them in the right win32 datatype (HWND/IntPtr(in C#)).

Unfortunately, this solution poses a new problem for me, which I''ll go ahead and put in a new post, but will mention here. The windows I now can access through code are the exact same ones I can see in spy++, but there are many other controls on this page that don''t show up in spy ++...and I really need to know why. I cannot access them so far by code either...using FindWindowByIndex() or any other way. I''ll post this new one elseware.

Here''s the solution:

// Finding Controls By Index
Console.WriteLine("Finding handle to Index_1");
IntPtr indx1 = FindWindowByIndex(mwh, 1);
if (indx1 == IntPtr.Zero)
    throw new Exception("Unable to find Index_1");
else
    Console.WriteLine("Handle to Index_1 is " + indx1);
Console.WriteLine("Finding handle to Index_2");
IntPtr indx2 = FindWindowByIndex(mwh, 2);
if (indx2 == IntPtr.Zero)
    throw new Exception("Unable to find Index_2");
else
    Console.WriteLine("Handle to Index_2 is " + indx2);

        // Finding Controls By Index
        Console.WriteLine("Finding handle to Index_B1");
        IntPtr indxb1 = FindWindowByIndex(indx2, 1);
        if (indxb1 == IntPtr.Zero)
            throw new Exception("Unable to find Index_B1");
        else
            Console.WriteLine("Handle to Index_B1 is " + indxb1);
        Console.WriteLine("Finding handle to Index_B2");
        IntPtr indxb2 = FindWindowByIndex(indx2, 2);
        if (indxb2 == IntPtr.Zero)
            throw new Exception("Unable to find Index_B2");
        else
            Console.WriteLine("Handle to Index_B2 is " + indxb2);
        Console.WriteLine("Finding handle to Index_B3");
        IntPtr indxb3 = FindWindowByIndex(indx2, 3);
        if (indxb3 == IntPtr.Zero)
            throw new Exception("Unable to find Index_B3");
        else
            Console.WriteLine("Handle to Index_B3 is " + indxb3);
        SetForegroundWindow(indxb3);
                // Finding Controls By Index
                Console.WriteLine("Finding handle to Index_C1");
                IntPtr indxc1 = FindWindowByIndex(indxb3, 1);
                if (indxc1 == IntPtr.Zero)
                    throw new Exception("Unable to find Index_C1");
                else
                    Console.WriteLine("Handle to Index_C1 is " + indxb1);
                {
                    System.Threading.Thread.Sleep(200);
                }
                SendKeys.SendWait(" ");
                {
                    System.Threading.Thread.Sleep(200);
                }
                SendKeys.SendWait("{TAB}"); ...


这篇关于需要通过p/invoke和findwindowex()查找子窗口的示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆