0

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, ...) 找出按钮的功能:

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, "Button", null);
                if (result != IntPtr.Zero)
                    ++ct;
            }
            while (ct < index && result != IntPtr.Zero);
            return result;
        }
    }

但是程序没有按下另一种形式的第一个按钮(索引 0 按钮)

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

4

2 回答 2

1

class参数 to与FindWindowExC# 中的类名不同。它是窗口类名称,在您调用GetClassName时返回。

例如,在我的系统(Windows 7 Enterprise、.NET 4.5、Visual Studio 2012)上运行的以下代码显示"Classname is 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类静态构造函数生成的,并且随着程序的每次执行而变化。所以你不能使用完整的类名。

可能可以查找 substring ".BUTTON.",甚至可能".BUTTON.app.0",因为它似乎是恒定的。您甚至可以检查字符串是否以 开头"WindowsForms",但我不建议添加"10",因为我怀疑这是版本号。

无论您在此处做什么,请注意您正在处理未记录的 Windows 窗体实现细节,这些细节可能随时发生变化。

于 2013-06-25T19:40:28.630 回答
0

您应该使用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;
    }

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

于 2013-07-11T12:11:55.823 回答