こんにちは。
現在、WindowsXP、Visual Studio2005(以下VS)にて既存のアプリケーションの操作を行うツールを作成しようとしています。
Findwindow関数で親のハンドルをとり、EnumChildWindow関数でコントロールのハンドルを取得しましたが、操作したいボタンの情報が取れません。
参考にさせていただいたコードは以下です。
http://blog.goo.ne.jp/masaki_goo_2006/e/cea1b601 …

VS付属spy++の調査も同様の結果で、そのボタンの情報が出てきませんでした。
コントロールの情報がとれないという事はあるのでしょうか?

ちなみにボタンはtoolbarの上にありtoolbarの情報は取れています。

情報が取れない場合、操作は出来ないということでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (4件)

 こんにちは。

ツールボタンのどの情報を取りたいのでしょうか。
 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;
}
    • good
    • 0
この回答へのお礼

具体的な例ありがとうございます。
とても参考になります。

>ツールボタンのどの情報を取りたいのでしょうか。

やりたいことはそれぞれのボタンを押すことです。
その為のツールバー上のボタンのハンドル?をどのようにとればよいかわかりませんでした。

なかなか難しい内容で時間がかかるかもしれませんが
いただいた情報を頼りになんとか確認してみたいと思います。

お礼日時:2009/05/23 01:25

 こんにちは。

御礼頂きました。
 すっかり見落としていました。プログラムからツールボタンを操作するのが目的でした。
 此れに関して回答すると、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上では両方とも動きます)。
    • good
    • 0
この回答へのお礼

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

しかし調べてみたところTB_ISBUTTONCHECKEDなどの他のメッセージを使えばこの辺の特定がうまく出来そうなので組み込んでみたいと思います。

お礼日時:2009/05/26 10:48
    • good
    • 0
この回答へのお礼

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

お礼日時:2009/05/23 01:20

ツールバーのボタンはボタンのようでボタンではありません。

あくまでツールバーの一部です。

なので、情報を取得するには、ツールバーのメッセージを使うとよいでしょう。
    • good
    • 0
この回答へのお礼

ありがとうございます。

ボタン(のようなもの)が10個くらいついているのですが
どのボタンかを特定するのはどうすればいいのでしょうか?

一つは位置情報かなと考えているのですが。

お礼日時:2009/05/22 15:01

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q社内向けiPhoneアプリのアップデート方法について

社内向けiPhoneアプリのアップデート方法について

一般のアプリと違い、iPhoneDeveloperEnterpriseという開発ライセンスを取得し、iPadアプリを開発しました。
配布方法はiPhone構成ユーティリティやiTunesからのみとなっており、AppStoreには登録出来ない仕様です。(たぶん)

そんな中、一つ困っているのが、アプリのアップデートです。
プログラムをバージョンアップする度に、アプリが再インストールされ、その度にアプリ内部に保存していたデータが
消えてしまいます。。。

今後、保存データは数も量も多くなるため、毎回消えてしまっては困ります。。
アプリの機能として社内サーバからデータを再取得する機能は用意しましたが、1台当り10GBの量になるため、
現実的ではありません。

他の方法としては、アプリ内にリソースとしてデータを付けてインストールする方法もありますが、
人によって持つデータが異なる仕様のため、厳しいです。

AppStoreのアプリのようにアップデートできる方法はないでしょうか?
ご存知の方でなくても、何か解決策のアドバイスを頂きたいので、いろんな意見をお願いいたしますm(__)m

対象端末:iPad(OS 3.2.2) 300台

社内向けiPhoneアプリのアップデート方法について

一般のアプリと違い、iPhoneDeveloperEnterpriseという開発ライセンスを取得し、iPadアプリを開発しました。
配布方法はiPhone構成ユーティリティやiTunesからのみとなっており、AppStoreには登録出来ない仕様です。(たぶん)

そんな中、一つ困っているのが、アプリのアップデートです。
プログラムをバージョンアップする度に、アプリが再インストールされ、その度にアプリ内部に保存していたデータが
消えてしまいます。。。

今後、保存データは数も量も多...続きを読む

Aベストアンサー

データの保存場所に、まちがいはありませんね。

専門家、経験者ではない素人の発想ですが、アプリの上書きでなく、アプリの追加になっていませんか?つまりホーム画面で、アイコンが増え続けていませんか?

※「iPhoneDeveloperEnterpriseという開発ライセンス」は、そうとう高額なのではありませんか?だとしたら、なんら遠慮することなく、アップル(ADC)に問い合わせるべきだと思います。英語じゃないと応対できないのかもしれませんが。

QC(C++) コントロール(ボタン)の制御 ボタン1押したらボタン2が使用不可に・・・その逆も。。。

はじめまして。

回りに聞ける人がいなくて困ってます。

C(C++)でフォームにボタンを設置し、任意のボタンを押したら、他のボタンが押せなくなるように、
もう1回押したら、他のボタンが押せるように戻るっていう感じの制御をしたいのですが、書き方が分かりません。

分かる方、記述例をつけて教えて頂けると助かります。お願いします。

Aベストアンサー

こんんちは

ボタン1を押したらボタン2の有効/無効を最クリックに切り替えると言ううことでよね?
ボタン1が押されたときのハンドラのみ記述します。
参考にしてみてください。

有効=ボタンが押せる状態
無効=ボタンが押せない状態

void CMyDlg::OnButton1()
{
CButton*pBtn = (CButton*)GetDlgItem(IDC_BUTTON2);

// ボタン2が有効か無効かをチェック
if( pBtn->IsWindowEnabled() ){
// 有効なら無効にする
pBtn->EnableWindow(FALSE);
} else {
// 無効なら有効にする
pBtn->EnableWindow(TRUE);
}

}

Qiphone5s、アプリのアップデートができない

iphone5sです、iosは7.0.3 です。

APPストアに10のアップデートマークがついたので、アップデートしようと思い、アップデートの画面を開きましたが、、まず右上の「すべてをアップデート」がグレーアウトしています。仕方なく個別のアップデーとボタンをタップすると、タップしたアプリが起動するだけでアップデートができません。10個とも試しましたがすべて開くだけでアップデートになりません。
自分で試したことは、iphone自体を再起動、AppStoreアプリを再起動、wifiに接続してみる、ですがすべて効果なしでした。試しにアップデートできないアプリの一つ「google」を削除して、APPストアからダウンロードしてみましたが、これは正常にできました。

よろしくお願いします。

Aベストアンサー

現在のアップデートは殆どがiOS8対応の物と考えますが?

アプリによってはiOS7対応の物がダウンロードされる時が
有りますが、やはりアップデートマークはそのままと考えます。

*『アップデートはこの機種に対応してません。』と言われてませんか。

QVC++2005EEでPowerPointの操作

Microsoft Office PowerPoint 2003でつくったプレゼン中にテンキー等のキーがおされたら、指定したページのスライドに移動するという常駐プログラムをVisual C++ 2005 Express Editionで作ろうとしています。
いろいろ調べてみたら、PowerPointのスライドを操作するにはAPIという関数が必要などいろいろとあったのですが、指定したページのスライドに移動をできるようなことが書かれたサイトはみつかりませんでした。

そもそも、PowerPointのスライドを外部プログラムで操作することは可能なのでしょうか?
もしできるのなら、サイトか構文などをおしえてもらえないでしょうか?

Aベストアンサー

参考になるサイト情報を教えて頂き有難う御座いました。
COMは情報をかき集めるのが結構大変です。一応、少ないですがCOM
オブジェクトを使ったプログラミングの参考書も出版されているの
で、そちらも購入されると良いと思います。検索ワードはCOM、ATL
等のキーワードです。

COMは・・・う~ん、うまい言葉が見つからないんですが、この場合、
PPTの制御用にmicrosoftが開発した命令セットをプログラム上で我々
が使う為の仕組みです。

PPT意外でも、メディアプレイヤー、WORD用のCOMオブジェクトという
のもあります。ユーザーはCOMを上手に使う事で仰る様な製品の制御
を行える様になるかも知れません。

ただ、何が出来るかは、公開されたインターフェースの機能に依存し、
それを調べる事から始めないといけません。PPT位メジャーなもので
あれば情報入手もある程度可能かもしれませんが、まず、そこが壁
です。それが分かれば、後は呼び出す為の規約通りに初期化して生成
してメソッドを使って破棄してと言うような感じの流れです。

恐らく、下のリンクのサンプルは非常に理解の助けになるはずです。

あと、常駐と組み合わせるよりは、このCOMを使ったアプリを作成して、
PPTのファイルをそのアプリにドラッグドロップし起動させれるよう
にして、それを使ってスライドショーを行う場合に上記の機能が
使えるという様なアプリ構成にした方が作りやすいと思います。
常駐だと、多分、起動するアプリの拡張子を見張るとかの処理が必
要になりそうで面倒に感じます。

おなじ言葉でCOMポートというものも存在するので間違えない様にし
てください。これは全く別物です

自分もそこまで詳しくはないので、参考にならなかったら御免なさい。
一応、何か追加で補足があれば付け加えておいてください。^^;)

参考になるサイト情報を教えて頂き有難う御座いました。
COMは情報をかき集めるのが結構大変です。一応、少ないですがCOM
オブジェクトを使ったプログラミングの参考書も出版されているの
で、そちらも購入されると良いと思います。検索ワードはCOM、ATL
等のキーワードです。

COMは・・・う~ん、うまい言葉が見つからないんですが、この場合、
PPTの制御用にmicrosoftが開発した命令セットをプログラム上で我々
が使う為の仕組みです。

PPT意外でも、メディアプレイヤー、WORD用のCOMオブジェクトと...続きを読む

QAndroidでアプリのアップデートに失敗したのにも関わらず容量が減ってしまった

Androidスマホで、アプリのアップデートに失敗しました。
失敗したのにも関わらず、本体容量が減ってしまいました。
減った容量を戻す方法があれば教えてください。

Aベストアンサー

アップデートを成功させるか
一度そのアプリを削除して再インストールしたら
いいと思いますよ
ゴミ箱機能がオンになっているなら
ゴミ箱を空にして下さい
キャッシュや履歴のクリーンアップをして下さい

QFindWindowの戻り値が違う!?

いつもお世話になっております。
FindWindowの戻り値についてご教授願います。

ret = FindWindow(NULL,"sample");
上記を実行した場合、取得する画面がアクティブの時と非アクティブの時でFindWindowの戻り値が違うのは何故でしょうか?

私は、sample画面が非アクティブでもアクティブ状態の時と同じハンドルが取得したのですが、良い方法は有りますでしょうか?

取得画面タイトル:sample
実行ファイル名:sample.exe

実行環境:WindowsXP
開発環境:VC++ 6.0

Aベストアンサー

No.1, No.2 への補足読みました。

VC++ に付属の Spy++ というツールを使うと,任意のウィンドウのウィンドウクラス名を調べることができます。
使い方は参考 URL を。

これで調べたウィンドウクラス名を,FindWindow の第1引数に渡してやればよいです。

ただし,ウィンドウクラス名は一意ではないので,確実に目的のウィンドウのハンドルが取れる保証はありません。
要は仕様でどこまで要求されるかですが,それじゃ困るという場合には別な方法を考えないといけませんね,ということで。

参考URL:http://www.microsoft.com/japan/developer/library/vcug/_asug_using_the_window_finder_tool.htm

Qアプリの削除方法を教えて下さい

iPhoneにアプリをインストールしてそれがいらないアプリだったので削除したのですがアップデートの購入済みアイテムに入っています。それも全て削除したいのですがどうしたらいいのですか?
全くわかりません。削除する方法を教えて下さい。
宜しくお願いします。

Aベストアンサー

下のひとの言ったことをしたあとにipod(iphone)に無いアイテムを選び削除したいものを左にスライドする
そうすると削除できる

Q他フォームのコントロールを直接操作することについて

私は度々、質問者の方が他のフォームのコントロールを直接操作するコード(Controlsプロパティ経由であったりアクセスレベルをpublicなどにしてあったり)書かれているのを見ると「(設計上の理由で)他フォームのコントロールを直接操作するのはお勧めしません」とアドバイスのつもりで書いてたりするのですが(毎度それを読まされてうんざりされてる方もいるかもしれませんが)、その「他のフォームのコントロールを直接操作するのはお勧めしない」ということはおかしい事でしょうか?
私は汎用性などを考え設計的な理由でそういってるわけで(理想をいえばモデルを用意することなんでしょうが、そこまでいうつもりはないです)、技術的理由でいってるわけじゃないです。

元ネタは
http://oshiete.goo.ne.jp/qa/7582043.html
なのですが正直相手にするのに疲れたので他の方の意見もお聞きしたいと思ったしだいです。

Aベストアンサー

> オーナースレッドが同じなら他フォームのコントロールを直接操作しても問題はない。

確かに「例外要因にならない」って意味では問題ないでしょうが、オーナースレッドが同じ場合とそうでない場合で異なるコードを書くのは徒に混乱を招くだけなので、例外が発生する(=オーナースレッドが別である)ことを前提に書くのが普通でしょうねぇ。
フォームの可搬性とか以前の問題で、状況により例外が発生してしまうようなコードは基本的にNGでしょう。
#例外でトラップする以外にエラーチェックしようがないケースはもちろん除きますが

QApple購入済のアップデート遍歴について教えて下さい。 彼が出会い系アプリは過去に使っていた事はあ

Apple購入済のアップデート遍歴について教えて下さい。
彼が出会い系アプリは過去に使っていた事はあるけど、今は使っていないと言ったのですが、何となく見てたらアップデート遍歴というのがあり、毎月アップデートされていました。
現在使っていないアプリでもアップデートされ、アップデート遍歴に日付が出たりするのでしょうか?
それともいくつかデバイスがあるのでアプリを使っているという事でしょうか?

Aベストアンサー

アップデートは選択してすることも出来るのですが、しょっちゅうあるから、まとめてアップデートするのが楽なんです。その時に一緒にアップデートされちゃうのでしょう。
嫌ならそのアプリを目の前で削除してもらったら?

Q子フォームから親フォーム上のコントロールを操作したい

VC++.NET(C++/CLI)にてアプリケーションを開発しております。
親フォーム(FormParent)と子フォーム(FormChild)があり
子フォームから親フォーム上にあるtextBox1を操作したいのですがうまくいきません。

親フォームからはFormChild.hをインクルードすることで
親フォームのインスタンスを得て、子フォームを表示させているのですが
これに加えて子フォームからFormParent.hをインクルードすると循環参照(と言うのですか?)
となる為にエラーになってしまいます。

よろしくお願いします。

Aベストアンサー

VC++は使ってませんのでC/C++一般の問題としての回答です。

子フォームのヘッダファイル内で親ファイルのヘッダをインクルードしてませんか?
それなら、子フォームのソースファイル(*.cpp)内でインクルードするようにすればよいはずです。

ただ、子フォームから親フォームが見えるようにする(親フォームのヘッダをまるまるインクルードする)のはあまり綺麗な設計とは思えません。

子フォームにtextBoxを操作する関数を作り、引数としてtextBoxのポインタなり参照なりを渡すようにすれば、子フォームが親フォームのヘッダをインクルードする必要はなくなりますが。
※子フォームは当然textBoxの型は知っているという前提。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング