C# 查找进程中的所有按钮(API函数)

C# 查找进程中的所有按钮(API函数),c#,api,function,C#,Api,Function,1。我有一个应用程序,试图从另一个表单中查找所有按钮。我将使用下面3个API函数: [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle); [DllImport("user32.dll", Set

1。我有一个应用程序,试图从另一个表单中查找所有按钮。我将使用下面3个API函数:

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
在我的程序中,我检查要检查的应用程序是否正在运行,如果为真,我将执行下一步操作:

    Process[] uWebCam = Process.GetProcessesByName("asd.vshost");
    if (uWebCam.Length != 0)
    {
        IntPtr ptr = uWebCam[0].MainWindowHandle;
        IntPtr x = FindWindowByIndex(ptr, 0);

        const int BM_CLICK = 0x00F5;
        SendMessage(x, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
    }
这就是我试图通过索引(0,1,…)找出按钮的函数:

静态IntPtr FindWindowByIndex(IntPtr hwndpresent,int index)
{
如果(索引==0)
返回hWndParent;
其他的
{
int-ct=0;
IntPtr结果=IntPtr.0;
做
{
结果=FindWindowEx(hWndParent,结果,“按钮”,null);
如果(结果!=IntPtr.Zero)
++ct;
}
而(ct<索引和结果!=IntPtr.Zero);
返回结果;
}
}
但程序并没有按下另一个窗体的第一个按钮(索引0按钮)


2.是否有任何程序可以从正在运行的进程中找到所有按钮的名称?我尝试了Spy++,但没有发现任何有用的东西…

FindWindowEx的
类的
参数与C#中的类名不同。它是窗口类名称,在调用时返回

例如,下面在我的系统(Windows 7 Enterprise、.NET 4.5、Visual Studio 2012)上运行的代码显示
“类名为WindowsForms10.BUTTON.app.0.b7ab7b_r13_ad1”
。这就是我第一次运行它时显示的内容。下次返回的值不同时

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hwnd, StringBuilder lpClassName, int nMaxCount);

private void button1_Click(object sender, EventArgs e)
{
    int nret;
    var className = new StringBuilder(255);
    nret = GetClassName(button1.Handle, className, className.Capacity);
    if (nret != 0)
        MessageBox.Show("Classname is " + className.ToString());
    else
        MessageBox.Show("Error getting window class name");
}
窗口类名显然是由
按钮
类静态构造函数生成的,并且随着程序的每次执行而改变。所以不能使用完整的类名

您可能可以查找子字符串
“.BUTTON.”
,或者甚至可能查找子字符串
“.BUTTON.app.0”
,因为它看起来是常量。您甚至可以检查字符串是否以
“WindowsForms”
开头,但我不建议添加
“10”
,因为我怀疑这是版本号


无论您在这里做什么,请注意,您正在处理未记录的Windows窗体实现详细信息,这些信息可能随时更改。

您应该使用
EnumChildWindows()
查找所有子窗口

Api函数:

  public delegate bool EnumChildCallback(IntPtr hwnd, ref IntPtr lParam); 

  [DllImport("user32.dll")]
  public static extern int EnumChildWindows(IntPtr hwnd, EnumChildCallback Proc, int lParam);

  [DllImport("User32.dll")]
  public static extern int SendMessage(int hWnd, int uMsg, int wParam, string lParam);
System.Diagnostics.Process[] uWebCam = Process.GetProcessesByName("asd.vshost");
            if (uWebCam .Length > 0)
            {
                foreach (System.Diagnostics.Process p in uWebCam )
                {
                    IntPtr handle = p.MainWindowHandle;
                    EnumChildWindows(handle, EnumChildProc, 0);
                }
            }
            else
            {
                MessageBox.Show("Process can not be found!");
            }
EnumChildWindows:

  public delegate bool EnumChildCallback(IntPtr hwnd, ref IntPtr lParam); 

  [DllImport("user32.dll")]
  public static extern int EnumChildWindows(IntPtr hwnd, EnumChildCallback Proc, int lParam);

  [DllImport("User32.dll")]
  public static extern int SendMessage(int hWnd, int uMsg, int wParam, string lParam);
System.Diagnostics.Process[] uWebCam = Process.GetProcessesByName("asd.vshost");
            if (uWebCam .Length > 0)
            {
                foreach (System.Diagnostics.Process p in uWebCam )
                {
                    IntPtr handle = p.MainWindowHandle;
                    EnumChildWindows(handle, EnumChildProc, 0);
                }
            }
            else
            {
                MessageBox.Show("Process can not be found!");
            }
EnumChildProc:在此处编写
SendMessage()
函数

 public bool EnumChildProc(IntPtr hwndChild, ref IntPtr lParam)
    {
        SendMessage(hwndChild.ToInt32(), WM_SETTEXT, 0, textBox1.Text);
        return true;
    }

我希望这些代码对您有所帮助。

谢谢您,吉姆,但是有了您提供的代码和解释,我无法解决我的问题。。。我试图得到它的按钮的过程,它不是用C#制作的,我也没有它的源代码。。。所以我只想访问这个过程的一个按钮…@charqus:我建议您编写一些调用
EnumChildWindows
的代码,将您感兴趣的顶级窗口的句柄传递给它。在回调函数中,调用
GetClassName
,并输出每个窗口的返回值。您还可以向窗口发送
WM_GETTEXT
消息(不要尝试在另一个进程中的控件上使用
GetWindowText
)来获取标题。所有这些都将帮助您识别按钮。然后你可以把你学到的东西整合到你真正想写的程序中。实际上,这是我试图接收它的按钮的进程的类名:ARCSOFT\uuuuu Magiccapp\uuuuuu WINDOW\uuuuuuu CLASS\uuuuw(我在AutoIT中发现的);从这里,是否可以访问它的按钮?这里是一个屏幕截图:您必须在顶级窗口上调用
EnumChildWindows
,并检查所有返回窗口的类名。这是确定按钮类名称的唯一方法。我搜索了很多以获得一个好的EnumChildWindows,并列举了我应用程序的所有窗口,但找不到一个好的。你能帮我做一个可行的函数,或者类似的东西吗?我的流程名称是:uWebCam