试图从子窗口获取“按钮”

时间:2013-11-30 20:17:17

标签: c# pinvoke

我首先要说的是,我对pinvoke的体验非常有限。我也很少了解C ++。但这是我的情况......

我在C#中有一个程序,它使用pinvoke从C ++中获取SendMessageFindWindow之类的函数。它查找窗口的名称,获取句柄等。现在工作正常。我会把代码放低一点。

现在我有一种情况,我想在其中一个子窗口上找到一个“按钮”。我有{strong>实际子窗口的IntPtr,至少我认为是。我很困惑什么是窗户,什么不是。

我正在尝试使用EnumChildWindowsFindWindowByCaption以及FindWindowEx等来检查所有孩子并找到此按钮。我可以用Spy ++获得它的“标题”,但是将它赋予FindWindowByCaption并不能产生任何结果。

这是实际找到父窗口的代码。如果它令人困惑,我很抱歉,它是针对非常旧的软件运行的。

这一切都在C#中,使用pInvoke。我尝试用这种方法首先得到我想要的按钮..

FindWindowByCaption(IntPtr.Zero, "{{Caption as shown by Spy++}}");

这不起作用,即使我给它正确的标题。所以我试试这个......在这个例子中,Handle是包含我想要找到的按钮的父窗口的IntPtr

// create a small counter so that we do not try to check
// too many windows and crash the program.
int i = 0;
var previous = new Window();
var current = new Window();

do {

    current = 
        new Window(
            InteropServices.FindWindowEx(
            Handle,
            previous.Handle,
            null, null
        )
    );
    if (current == IntPtr.Zero)
        break;

    // add current to list

    // continue
    previous = current; // never finds the right button, either.
    ++i;
} while (i < 500);

但即便如此,我想要的控制也永远找不到。谁能帮我这个?它变得非常令人沮丧。我可以在Spy ++中看到Caption,我可以看到它有一个句柄。它看起来并不特别。

1 个答案:

答案 0 :(得分:3)

您需要执行以下操作:

  1. 致电FindWindow以查找顶级窗口。使用类名或窗口标题或两者来标识它。
  2. 反复调用FindWindowEx以查找子窗口。将父窗口传递为hwndParent,将NULL传递为hwndChildAfter。再次使用类名或窗口标题或两者来标识子窗口。
  3. 最终,您将下降父/子窗口层次结构,直到到达目标窗口。
  4. 因此,举个例子,使用Spy ++表示法考虑以下层次结构:

    Window 00001000 "My MainForm window title" "MainFormWindowClass"
    |
    -- Window 00002000 "Panel container" "PanelWindowClass"
       |
       -- Window 00003000 "Click me!" "ButtonWindowClass"
    

    您可以通过以下调用序列找到它:

    HWND main = FindWindow("MainFormWindowClass", NULL); // just use class name
    HWND panel = FindWindowEx(main, NULL, "PanelWindowClass", "Panel container");
    HWND button = FindWindowEx(panel, NULL, "ButtonWindowClass", "Click me!");
    

    请注意,我是用C ++编写的,以避免与p / invoke混淆。为了一个干净的例子,我也省略了所有的错误检查。你显然会检查错误。

    我建议您保留Spy ++,并尝试编写一个简单的C ++控制台应用程序来定位您的窗口。一旦您知道执行该作业的FindWindowFindWindowEx的调用顺序,请将它们翻译为C#。