• ベストアンサー

他のアプリケーションの操作について

こんにちは。 現在、WindowsXP、Visual Studio2005(以下VS)にて既存のアプリケーションの操作を行うツールを作成しようとしています。 Findwindow関数で親のハンドルをとり、EnumChildWindow関数でコントロールのハンドルを取得しましたが、操作したいボタンの情報が取れません。 参考にさせていただいたコードは以下です。 http://blog.goo.ne.jp/masaki_goo_2006/e/cea1b601e33fb7a344ecba2ee972efe4 VS付属spy++の調査も同様の結果で、そのボタンの情報が出てきませんでした。 コントロールの情報がとれないという事はあるのでしょうか? ちなみにボタンはtoolbarの上にありtoolbarの情報は取れています。 情報が取れない場合、操作は出来ないということでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

 こんにちは。ツールボタンのどの情報を取りたいのでしょうか。  SendMessage() TB_???のメッセージで情報を受け取る際、構造体等のポインタを必要とするものが多数ありますが、他プロセスのウィンドウハンドルに向かって此方側のポインタを渡してみた所で、向こう側からしてみれば「寝耳に水」も良い所です。  プロセス間共有メモリを仲介して、データをやり取りする事になります。どちらにしろ、そんな簡単な事ではありません。  以下ではVirtualAllocEx()を使用していますが、windows xpで上手くいくかはわかりません(windows 2000sp4の上では上手くいっています)。  参考資料程度に。 #include<tchar.h> #include<windows.h> #include<commctrl.h> #include<stdio.h> typedef struct ProcessMemory { DWORD dwProcessID; DWORD dwThreadID; HANDLE hProcess; union { LPVOID pVoid; LPBYTE pByte; LPARAM lParam; }; } PROCESSMEMORY, *LPPROCESSMEMORY; static BOOL OpenProcessMemory(LPPROCESSMEMORY p, HWND hWndOutProcess, DWORD dwSize) { p->dwThreadID = ::GetWindowThreadProcessId(hWndOutProcess, &p->dwProcessID); if(!p->dwThreadID || !p->dwProcessID) return FALSE; p->hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, p->dwProcessID); if(!p->hProcess) return FALSE; p->pVoid = ::VirtualAllocEx(p->hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); return p->pVoid != NULL; } static BOOL CloseProcessMemory(LPPROCESSMEMORY p) { if(!p->hProcess) return FALSE; ::VirtualFreeEx(p->hProcess, p->pVoid, 0, MEM_RELEASE); ::CloseHandle(p->hProcess); ::ZeroMemory(p, sizeof(PROCESSMEMORY)); return TRUE; } static DWORD WriteProcessMemory(LPPROCESSMEMORY p, DWORD dwByteOfOffset, const void* pIn, DWORD dwSizeOfIn) { DWORD dwLen = 0; ::WriteProcessMemory(p->hProcess, &p->pByte[dwByteOfOffset], pIn, dwSizeOfIn, &dwLen); return dwLen; } static DWORD ReadProcessMemory(const LPPROCESSMEMORY p, DWORD dwByteOfOffset, void* pOut, DWORD dwSizeOfOut) { DWORD dwLen = 0; ::ReadProcessMemory(p->hProcess, &p->pByte[dwByteOfOffset], pOut, dwSizeOfOut, &dwLen); return dwLen; } int main() { //見つかっているものとする HWND hWndOutProcess = ::FindWindow(_T("Afx:400000:b:10011:6:7042d"), NULL); HWND hWndCtlBar = ::FindWindowEx(hWndOutProcess, NULL, _T("AfxControlBar42d"), NULL); HWND hWndToolBar = ::FindWindowEx(hWndCtlBar, NULL, TOOLBARCLASSNAME, NULL); //他プロセスのメインウィンドウ PROCESSMEMORY pm = {0}; ::OpenProcessMemory(&pm, hWndOutProcess, sizeof(TBBUTTON)); //他プロセスのツールバーの数を取る const int count = ::SendMessage(hWndToolBar, TB_BUTTONCOUNT, 0, 0); for(int i = 0; i < count; ++i) { //受け皿 TBBUTTON tbb = {0}; //プロセス間共有メモリをゼロで初期化 ::WriteProcessMemory(&pm, 0, &tbb, sizeof(TBBUTTON)); //他プロセスのツールボタンメッセージ→プロセス間共有メモリ ::SendMessage(hWndToolBar, TB_GETBUTTON, i, pm.lParam); //プロセス間共有メモリ→受け皿 ::ReadProcessMemory(&pm, 0, &tbb, sizeof(TBBUTTON)); //取りあえず表示 ::printf("[ボタン番号 : %d][ボタン状態 : %d][ボタンスタイル : %d][ボタンID : %d][ビットマップ番号 : %d]\n", i, tbb.fsState, tbb.fsStyle, tbb.idCommand, tbb.iBitmap); } ::CloseProcessMemory(&pm); return 0; }

itouke77
質問者

お礼

具体的な例ありがとうございます。 とても参考になります。 >ツールボタンのどの情報を取りたいのでしょうか。 やりたいことはそれぞれのボタンを押すことです。 その為のツールバー上のボタンのハンドル?をどのようにとればよいかわかりませんでした。 なかなか難しい内容で時間がかかるかもしれませんが いただいた情報を頼りになんとか確認してみたいと思います。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.4

 こんにちは。御礼頂きました。  すっかり見落としていました。プログラムからツールボタンを操作するのが目的でした。  此れに関して回答すると、WM_COMMANDをツールバーの親ウィンドウに送るか、WM_LBUTTONDOWN/WM_LBUTTONUPにツールボタンの座標を指定してクリックされた事にすれば出来ます。 //メモリの割り当て PROCESSMEMORY pm = {0}; ::OpenProcessMemory(&pm, hWndOutProcess, sizeof(TBBUTTON)); //受け皿 TBBUTTON tbb = {0}; //必要があれば此処でhWndOutProcessを最前面に持ってくる //プロセス間共有メモリをゼロで初期化 ::WriteProcessMemory(&pm, 0, &tbb, sizeof(TBBUTTON)); //2番目のツールボタンの情報を取る ::SendMessage(hWndToolBar, TB_GETBUTTON, 1, pm.lParam); //プロセス間共有メモリ→受け皿 ::ReadProcessMemory(&pm, 0, &tbb, sizeof(TBBUTTON)); //ツールバーの親ウィンドウにWM_COMMANDを送る ::SendMessage(hWndCtlBar/*ツールバーの親ウィンドウを指定*/, WM_COMMAND, tbb.idCommand, (LPARAM)hWndToolBar); //メモリを閉じる ::CloseProcessMemory(&pm);  又は、 //メモリの割り当て PROCESSMEMORY pm = {0}; ::OpenProcessMemory(&pm, hWndOutProcess, sizeof(RECT)); //受け皿 RECT rc = {0}; //必要があれば此処でhWndOutProcessを最前面に持ってくる //プロセス間共有メモリをゼロで初期化 ::WriteProcessMemory(&pm, 0, &rc, sizeof(RECT)); //2番目のツールボタンの矩形領域を取る ::SendMessage(hWndToolBar, TB_GETITEMRECT, 1, pm.lParam); //プロセス間共有メモリ→受け皿 ::ReadProcessMemory(&pm, 0, &rc, sizeof(RECT)); //ツールバーのボタン上でマウスの左ボタンが押された事にする ::SendMessage(hWndToolBar, WM_LBUTTONDOWN, 0, MAKELONG(rc.left + 2, rc.top + 2)); //ツールバーのボタン上でマウスの左ボタンが離された事にする ::SendMessage(hWndToolBar, WM_LBUTTONUP, 0, MAKELONG(rc.left + 2, rc.top + 2)); //メモリを閉じる ::CloseProcessMemory(&pm);  と言った具合です(当方のPC上では両方とも動きます)。

itouke77
質問者

お礼

動作確認のため返信遅れました。 申し訳ありません。 ほぼいただいたコード通りで無事に押すことが出来ました。 ありがとうございます。とても助かりました。    ただ、ボタンが8個しかないのに、"TB_BUTTONCOUNT"で取得した数は19を示しています。 (この数の違いは何を示しているのかは後ほど知らべたいと思います。) 押せるボタンは8個ですのでどの番号がどのボタンを示しているのか、総当りで探した次第です。 しかし調べてみたところTB_ISBUTTONCHECKEDなどの他のメッセージを使えばこの辺の特定がうまく出来そうなので組み込んでみたいと思います。

全文を見る
すると、全ての回答が全文表示されます。
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.2
itouke77
質問者

お礼

ありがとうございます。 調べてみます。

全文を見る
すると、全ての回答が全文表示されます。
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.1

ツールバーのボタンはボタンのようでボタンではありません。あくまでツールバーの一部です。 なので、情報を取得するには、ツールバーのメッセージを使うとよいでしょう。

itouke77
質問者

お礼

ありがとうございます。 ボタン(のようなもの)が10個くらいついているのですが どのボタンかを特定するのはどうすればいいのでしょうか? 一つは位置情報かなと考えているのですが。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • javaプログラムから他のjavaプログラムを操作

    javaのプログラムから他のjavaプログラムを操作するにはどのようにすればいいのでしょうか? 他の方が作った既存のjavaプログラムのウィンドウ内のリストビューの項目を自動的に選択したり、エディットビューの表示文字列をクリップボードにコピーしたいと思っています。 Windowsネイティブプログラムから他のWindowsネイティブプログラムを操作する場合は、FindWindowで親ウィンドウのウィンドウハンドルを取得し、そこからFindWindowExで子ウィンドウのハンドルを取得してサブクラス化するそうですが、javaではどうやるのかが知りたいです。 また、子ウィンドウのハンドルを得るために子ウィンドウを特定するための情報(Windowsネイティブプログラムなら、FindWindowExに引数として渡す「GetClassNameで得られるクラス名」)はどのようにすれば調べられるのでしょうか(EnumChildWindows、GetClassNameなどに該当するメンバ関数はあるのでしょうか)?

    • ベストアンサー
    • Java
  • FinderSystem等のツールで取得できないハンドルを取得するには?

    他のアプリケーションのボタンで操作したいと思い FinderSystemやNuke++等のツールを使いウィンドウハンドルを調べ SendMessage関数を使ってコマンドボタンのクリックをする所までは できるのですが、ツール等でウィンドウハンドルを取得できないラベル トグルボタンが存在し、画面上では明らかに存在しているのですが そのボタンには反応せず、大きな枠組みでウィンドウハンドルを 取得してしまいます。FindWindow、FindWindowEx、GetWindow EnumChildWindowで子ウィンドウのハンドルまで調べたのですが 値が0になってしまいます。他にもボタンだけではなく タブコントロールも操作したいと思っているのですが 同様に子ウィンドウハンドルの値は0になってしまいます そもそもウィンドウハンドルを全て取得することは不可能なのでしょうか? いろいろな他のアプリケーションのコマンドボタンをFinderSystemで調べて 取得できる場合とできない場合があり、この差は何なのか 疑問に思っています。ご存知のお方がいれば お手数ですが教えていただけないでしょうか? 開発環境は、WindowsXP、VB6.0です。 宜しくお願いいたします。

  • 他のアプリの表示、非表示について

    他のアプリケーション(アプリA)をコントロールするプログラムを作っています。アプリAと自作アプリは起動したままです。自作アプリでボタンを押すとアプリAを表示させてアクティブにして仕事をさせ、終わったら非表示にします。 アプリAのハンドルをhandle = FindWindow()で取得して ShowWindow(handle,SW_SHOWNORMAL)で表示して、 ShowWindow(handle,SW_HIDE);で隠しています。 ボタンを押したときに、アプリAが表示されていると、非表示にしたあとタスクバーのアプリを手動で表示できません。 MINIMIZEやCloseWindos()も試しましたが、それだと画面の左下にアプリAが残ってしまいます。 SendMessage(handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);も試しましたがうまくいきません。使い方が悪いのかもしれません。 アプリAを隠す事と元のサイズで表示する。という二つの動作をプログラムで交互に行う場合に、途中で手動でアプリAの最小化、あるいはタスクバーから出すという動作をさせることができるのが希望です。どうすればよいでしょうか。 OSはXPです。

  • マイクロソフト コミュニティの操作方法

    マイクロソフト コミュニティに質問しました。参考になる回答が寄せられ「役に立つた」ボタンを押したのですが、”最も役にたっている投稿を回答としてマークしてください。”とのの催促がありました。が、「回答としてマ-ク」するのボタンが見当たりません。 https://answers.microsoft.com/ja-jp/windows/forum/windows_7-winapps/%E6%9C%80%E3%82%82%E5%BD%B9%E3%81%AB%E3%81%9F/df99f9e5-e1b4-4337-8882-a5edf1fb6a9f にも、そのような操作方法が掲載されているのですが、ボタンがありません! お分かりの方、お教えください。

  • VBAでのWebダウンロード制御ができない

    Windows7 IE10 の環境でEXCEL VBAからWebのダウンロードボタンを押すところまではできてますが、 通知バーのハンドルを取得できずに困っています。 以下のFindWindowのパラメータが悪いと思うのですが、何を指定すればいいのかわかりません。 ご教授、よろしくお願いします。 Do DoEvents p_lngFindWnd = FindWindow("#32770", "保存") lCntloop = lCntloop + 1      Loop While (p_lngFindWnd = 0 And lCntloop < 10000)

  • このツールはどこで入手できるか教えてください。

    以下のURLの画像の下の方にあるスクリーニングツールは何処で入手できるのでしょうか? ご教授お願い致します。 http://image.blog.livedoor.jp/u_tatane/imgs/e/e/ee8fb627.GIF

  • BMW525iハイラインのハンドルのボタン操作教えて~!

    読んでいただき感謝します。 2002年式BMW525iハイラインのハンドルに付いているボタンの操作に ついて教えて下さい。 向かって左側のボタンは携帯電話の操作やオーディオ関係のボリュームなどの操作に使用する事は分かりましたが、向かって左側のボタンが良く理解出来ません。 実は中古のBMWを購入しようと何件かの中古車屋さんを回ったのですが、ボタン操作についてはあまり把握出来ていないようです。 中には高速に入った時にアクセルを踏まなくても一定の速度で走行 する為のオートクルージングのような事を言われたのですが、それに してもどのように使うのかがまったく分かりません。 情報が少ないかも知れませんが詳しい方いらっしゃいましたら是非 教えて下さい。 よろしくお願いします。

  • A.C.E.2の操作方法について

    PS2ソフトの[A.C.E.2]の操作方法というかロックオンについてお聞きしたいのですが、 アーマード・コアと同じような自分でロックオンをする感じでしょうか? それともガンダムSEED 連合VSザフトのような ボタン一つでロックオンを勝手にしてくれる感じでしょうか? どうもロックオンが上手く出来ないので;; シューティングゲーム超初心者なので、 上手く出来る方法があればそちらもお聞きしたいです。 よろしくお願い致します。

  • [Haskell]handle関数がうまくいかない

    RealWorldHaskellという本を読んでいて解決できないところがあったので質問します。 Control.Exceptionには例外を扱うhandle関数というものがあります。 型シグネチャは Exception e => (e -> IO a) -> IO a -> IO a です。 1つ目の引数に例外を捉えた場合実行する関数を、2つ目の引数に例外を投げる可能性のある関数を与えます。 1つ目の引数の関数の返り値の型と2つ目の引数の型は同じでなければなりません。 次の関数はhandle関数を利用して安全にファイルサイズを取得する(つもりで作った)関数です。 getFileSize :: FilePath -> IO (Maybe Integer) getFileSize path = handle (\_ -> return Nothing ) $ bracket (openFile path ReadMode) hClose $ \h -> do size <- hFileSize h return (Just size) この関数がうまくいきません。 具体的に言えばコンパイルすると handle (\_ -> return Nothing ) の部分で Ambiguous type variable `e0' in the constraint: とエラーは吐きます。 しかし、返り値の型はNothingでMaybe Integerと合致していると思います。 なのにAmbiguousです。 なぜこうなるのかわかりません。 ちなみにControl.OldExceptionでもhandle関数が定義されていますが、ghcのバージョンが新しいせいか(7.0.2)コンパイルできません。 なのでControl.Exceptionしか使えません。 よろしくお願いします。

  • メッセージボックスの選択ボタンのテキストを変更したい

    メッセージボックスに表示される はい、いいえ、キャンセルのボタンのテキストを 自由に変更したいのですが何か良い方法があったら教えてください。 フォームを作ってメッセージボックスと同じものを作る方法ではなく、 MsgBox関数で表示されるものを変更したいです。 考え付いた方法ですが、メッセージボックスが表示された直後に APIのFindWindowなどでハンドルを調べて SendMessageでテキストを変更しようと思うのですが、 もっと良い方法があったらご教授いただけないでしょうか。 よろしくお願い致します。