试图获得“;按钮“;从儿童窗口

本文关键字:窗口 按钮 | 更新日期: 2024-06-14 08:57:50

我首先要说的是,我使用pinvoke的经验非常有限。我对C++也知之甚少。但我的情况是。。。

我在C#中有一个程序,它使用pinvoke从C++中获得SendMessageFindWindow等函数。它会查找窗口的名称、获取句柄等。这现在很好。我会把代码放低一点。

现在我有一种情况,我想在其中一个儿童窗口上找到一个"按钮"。我有实际子窗口IntPtr,至少我认为是。我对什么是窗口和什么不是窗口感到非常困惑。

我正在尝试使用EnumChildWindowsFindWindowByCaptionFindWindowEx等来浏览所有的孩子并找到这个按钮。我可以用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. 调用FindWindow查找顶级窗口。使用类名或窗口标题,或同时使用这两个名称来标识它
  2. 反复调用FindWindowEx查找子窗口。将父窗口作为hwndParent传递,将NULL作为hwndChildAfter传递。再次使用类名或窗口标题,或同时使用两者来标识子窗口
  3. 最终,您将下降父/子窗口层次结构,直到到达目标窗口

因此,举个例子,考虑以下层次结构,使用Spy++表示法:

Window 00001000"我的MainForm窗口标题"MainFormWindowClass"|--Window 00002000"面板容器"PanelWindowClass"|--Window 00003000"点击我!"按钮WindowClass"

您可以通过以下调用序列找到这一点:

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#。