Toshichan4
@Toshichan4

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

他プロセスで起動したハンドルのわかっているTextコントロールの Nameプロパティを取得する

解決したいこと

他プロセスで起動したハンドルのわかっているTextコントロールのNameプロパティを取得したいのですが、方法がわかりません。どなたかご教示願います。

他プロセスのフォームの中に複数の Text コントロールがあり、これらのコントロールのTextを読み書きしたいと考えています。
コントロールのハンドルは EnumChildWindows で列挙できるのですが、列挙したハンドルが複数のTextコントロールの中のどれか特定できず困っています。コントロールの位置情報を取得してこれをもとにどのコントロールのものか判断することもできるとおもいますが、「なんだかなー」という感じです。
Visual studio のリソースエディタでText コントロールを配置すると、Nameプロパティが設定されているので、これをもとに列挙したハンドルがどのコントロールのものか判定したいと考えていますが、ネットを調べてもこれができる情報に行き着きませんでした。ご存じの方があれば、ご教示いただけると幸いです。

0

3Answer

Comments

  1. @Toshichan4

    Questioner

    回答ありがとうございます。

    GetWindowTextWで、取得できませんか?

    リンクによると
    「指定したウィンドウのタイトル バーのテキスト (存在する場合) をバッファーにコピーします。 指定したウィンドウがコントロールの場合、コントロールのテキストがコピーされます。 ただし、 GetWindowText は別のアプリケーションのコントロールのテキストを取得できません。」
    とあります。
    他プロセスのコントロールには適用できないと思います。また、欲しいのはTextコントロールの Name プロパティ です。
    ちなみに、他プロセスの Text コントロールの Text を 読んだり書いたりすること自体はできています。( ただし、複数ある Text コントロールのどれに対して読み書きすればよいのか => 複数列挙されたどのハンドルが目的の Text コントロールのハンドルなのか明確に知ることができないので困っています。そのため、Text コントロールの Name プロパティ がわかれば、これが明確になると考えた次第です。

  2. ただし、 GetWindowText は別のアプリケーションのコントロールのテキストを取得できません。

    そのもう少し下に、以下の記載が。

    別のプロセスでコントロールのテキストを取得するには、GetWindowText を呼び出す代わりに、WM_GETTEXTメッセージを直接送信します。

    WM_GETTEXTSendMessageしてみてください。

  3. @Toshichan4

    Questioner

    ちなみに、他プロセスの Text コントロールの Text を 読んだり書いたりすること自体はできています。

    すでに、WM_GETTEXT を使って Text コントロールの読み込みはできています。 問題は 複数ある テキストコントロール(ハンドル)のどれにメッセージを送れば良いのかが明確に決定できないことです。

  4. なんか質問がループしているのですが。。。

    最初のご質問は、TextコントロールのNameプロパティが取得したいのでは?
    それに対して、GetWindowTextからのWM_GETTEXTをお答えしました。

    すでに、WM_GETTEXTしているなら、Nameプロパティを取得できていると思うのですが??
    もし、そうでなければ、WM_GETTEXTで取得したテキストは、なんでした?(具体的な文字列はなんでした?)


    ちなみに、既成のアプリのWindowClassやWindowTextを調べるだけなら、MS純正ツールのSpy++で見るのが簡単です。

    また、自動操作系のスクリプトを簡単に組めるUWSC等のフリーソフトがあります。
    マウス、キー操作を記録して再生することができますし、記録されたスクリプトをベースに自由にカスタマイズもできます。

  5. @Toshichan4

    Questioner

    テスト環境で、Textコントロールの読み書きをしたいアプリとして下の図のようなForm11_Id というタイトルのフォームを仮に作成しています。
    各コントロールのNameプロパティは、それぞれ textBox1, ……, textBox6 です。

    image.png

    この Form11_Id に対して 別のプロセス(今回作りたいアプリ)から EnumChildWindows して Textコントロールのハンドルを
    六つ取得できています。(例えば 101, 102, 103, 104, 105, 106)
    なので、これらのハンドルを使って

    SendMessage((Int32)hWnd, WM_SETTEXT, 0, "書きたいテキスト")

    してTextコントロールに"書きたいテキスト" を書き込むことはできますが、果たして textBox1 に書き込みたいときは SendMessage の hWnd に 101 を指定すれば良いのか、102 なのか はたまた別の番号なのか が分からないのです。
    例えば GetControlPropertyName(hWnd …)的なメソッドで 各ハンドル番号に対応するNameプロパティが分かれば、どの番号がどのTextコントロールのハンドルか判断できるので、「他プロセスで起動したハンドルのわかっているTextコントロールのNameプロパティを取得したい」 との質問になった次第です。

    すでに、WM_GETTEXTしているなら、Nameプロパティを取得できていると思うのですが??

    これが取得できておらず、その方法がまさに私が知りたい内容です。

    また、自動操作系のスクリプトを簡単に組めるUWSC等のフリーソフトがあります。

    これについては別途調べさせていただきます。情報をいただきありがとうございます。

  6. TextBoxですか。いま認識しました。
    そのNameプロパティは、C#のWindows.Formの世界のものなので、WIndows OSのAPIからは参照できないと思います。

    EnumChildWindowsで列挙される順番は、コントロールが生成される順番通りで、変わることはないはずです。
    よって、一度、列挙された順番にWM_SETTEXTしてみれば、順番とコントロールの位置(上図でいうtextBox1〜6)の関係が分かるはずです。

    textBox1 に書き込みたいときは SendMessage の hWnd に 101 を指定すれば良いのか、102 なのか はたまた別の番号なのか が分からないのです。

    列挙の順番とコントロールの位置が固定と分かれば、実現できませんか?

  7. @Toshichan4

    Questioner

    列挙の順番とコントロールの位置が固定と分かれば、実現できませんか?

    ありがとうございます。"列挙の順番とコントロールの位置が固定" ということであれば、一度試し書きしてみて列挙順のコントロールの位置を特定すればやりたいことはできると思います。
    何度か試験コードを走らせていて、どうやら列挙の順番とコントロールの位置は固定らしいとは感じていましたが、環境の違いなどで変わることはないのか、エビデンスが見つけられなかったので確信が持てず質問のような方法を探っていました。
    「固定なのかどうか」の質問をしたほうが良かったですね。

    ありがとうございます。

    ところで、

    そのNameプロパティは、C#のWindows.Formの世界のものなので、WIndows OSのAPIからは参照できないと思います。

    こういう情報は何にアクセスすれば得られるのでしょうか。ご教示いただければありがたいです。

  8. @Toshichan4

    Questioner

    すみません、改めてググってみたのですが

    このような記事があります。

    ここでは、最終的に コントロールの位置で判断という結論になっているようです。

  9. コントロールの位置で判断

    コントロールの座標ということならば、GetWindowRect で取得できます。

    textBox 1〜6 の位置関係が固定なら、座標から判断することは可能です。

  10. @Toshichan4

    Questioner

    そうですね。
    最初の質問の際に書きましたが

    コントロールの位置情報を取得してこれをもとにどのコントロールのものか判断することもできるとおもいますが、「なんだかなー」という感じです。

    実はこれも試していて、位置情報を取得できることも分かっているのですが、なんともスマートな方法じゃないような気がして質問に至った次第です。
    それに試していてわかったのですが、GetWindowRect などでとってきた位置情報をもとに算出した各コントロール間の相対距離と、リソースデザイナーが吐くコードのDrawing.Point から算出されるコントロール間の相対距離は異なっているので、環境によって変わってくる(何らかのスケーリングがされている)のだと思われます。
    (相対位置は相似だが相対距離は変化する)
    これを知って、ますます「なんだかなー」と思った次第です。

    とはいえ、もし、「列挙の順番とコントロールの位置は固定ではない」 となったらこれをやるしかないかもしれないですね。
    どこかにこれに関するMicrosoft のエビデンスがないですかね。

  11. 環境によって変わってくる(何らかのスケーリングがされている)のだと思われます。

    そうだと思います。
    しかし、位置関係は、それは関係ないと思います。
    例えば、「textBox1は、textBox4の左、textBox2の上に位置する」ことが確認できれば十分だからです。

    「列挙の順番とコントロールの位置は固定ではない」かも・・・

    コントロールの生成順序が固定で、生成後にZオーダーを変更しない ならば、列挙の順番が変わることは無いと思います。
    すべてのコントロールは、「親」「(兄弟)一つ前」「(兄弟)一つ後ろ」「最初の子」のウィンドウハンドルを保持しています。GetWindow, EnumWindowsEnumChildWindowsは、これらのチェーンをたどって目的のウィンドウハンドルを返します。
    順序を制御するのは、生成時の順番とZオーダーです。

    どこかにこれに関するMicrosoft のエビデンスがないですかね。

    Windows API以外の情報は分かりません。

  12. @Toshichan4

    Questioner

    承知しました。
    一旦、生成順が固定だと考えて先に進みたいと思います。
    問題が出ればまた後で、位置情報による特定等を考えることにします。

    長々とお付き合いいただきありがとうございました。

  13. 追伸;

    どこかにこれに関するMicrosoft のエビデンスがないですかね。

    ↓こちらを見る限り公式の明言は無さそうです。

    また、Zオーダー順だと言っています。

  14. @Toshichan4

    Questioner

    すみません。
    他の人のコメントに気を取られて、この追伸に対してご返事をしないまま質問をクローズしてしまいました。

    大変参考になります。
    ありがとうございました。

This answer has been deleted for violation of our Terms of Service.

これ使えばなんかいけそうな気もするけれど、自分で試した事ないんで使い方は聞かないでください。

0Like

Comments

  1. This comment has been deleted for violation of our Terms of Service.
  2. @Toshichan4

    Questioner

    情報をいただきありがとうございます。別途調べてみます。

    操作対象の変更にどこまで追随出来るかなど違いはありますが。

    操作対象は固定されているので問題ないのかなと考えています。

    (とはいえウィルス検出などに引っかかる)

    業務に使うのに、質問した操作は これが問題になるのかなと危惧している次第です。

  3. This comment has been deleted for violation of our Terms of Service.
  4. @Toshichan4

    Questioner

    私もその意味です。

    操作対象は固定されているので
     ⇒ 操作対象のプログラムバージョンは固定されているので

    失礼しました。

Your answer might help someone💌