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;
        }
    }

しかし、プログラムは別のフォームの最初のボタン ( index 0 button ) を押しません。

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クラスの静的コンストラクターによって生成され、プログラムの実行ごとに変化します。したがって、完全なクラス名は使用できません。

定数のように見える部分文字列、または場合によっては を探すことができる場合があります。文字列が で始まることを確認することもできるかもしれませんが、バージョン番号であると思われるため、 を追加することはお勧めしません。".BUTTON."".BUTTON.app.0""WindowsForms""10"

ここで何をするにしても、文書化されていない Windows フォームの実装の詳細を踏んでいることに注意してください。これはいつでも変更される可能性があります。

于 2013-06-25T19:40:28.630 に答える
0

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);

EnumChildWindows:

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 に答える