SendMessageの設定の仕方

解決


大和撫こ  2007-08-21 11:57:15  No: 66049  IP: 192.*.*.*

VC2005のMFCから
SendMessage(hwnd, WM_SETTEXT, 0, "処理終了です!" );
でAPIを使おうとしているのですが、
なぜか4個の引数は使えないのエラーが出ます。
SendMessageは4個の引数のはずなんですが?
何がおかしいのでしょうか?
MFCからSendMessageのAPIを使うには
インクルードや何かしらのインポートをしないと
いけないのでしょうか?
どなたか方法を教えてください。

編集 削除
Blue  2007-08-21 12:20:59  No: 66050  IP: 192.*.*.*

どのクラスの中で使っていますか?
CWndの派生クラスで使うと、CWnd::SendMessageが呼ばれてしまいます。
明に(メンバ関数ではなく)グローバルのSendMessageを使いたい場合は
頭に :: を付けるとうまくいくでしょう。

編集 削除
大和撫こ  2007-08-21 13:40:23  No: 66051  IP: 192.*.*.*

ご回答ありがとうございます!
教えてももらったように修正した。
ですが、また問題が起こりました。

スパイでクラス名を調べたところ
WindowsForms10.EDIT.app.0.14fd2b5とクラス名が分かりました。
FindWindowExでクラス名のところに
WindowsForms10.EDIT.app.0.14fd2b5としたところ
ハンドルがエラーになるので削っていくと
EDITでハンドルが取得できました。
取得できたのえSendMessageで送ったのですが。
まったく動作しません。
やはりハンドル取得のやり方が行けないのでしょうか?
コードを乗せましたので、間違いを指摘してもらえれば・・・・
と思います。
宜しくお願いします。
HWND hWnd;


hWnd = ::FindWindowEx(NULL, NULL, "EDIT", NULL);


::SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"処理終了です!" );

編集 削除
大和撫こ  2007-08-21 13:41:30  No: 66052  IP: 192.*.*.*

ちなみに送信先はVBの自作アプリです。

編集 削除
Blue  2007-08-21 13:43:40  No: 66053  IP: 192.*.*.*

>EDITでハンドルが取得できました。
本当にこれで間違いないですか?
Spy++でのウィンドウハンドルとFindExのウィンドウハンドルが一致していますか?

というか、別アプリのテキストボックスに値を入れたいってことでしょうか?
(だったらFindWindowExで親ウィンドウを指定しなくてもいいのかなぁと。)

編集 削除
Blue  2007-08-21 13:50:23  No: 66054  IP: 192.*.*.*

Spy++を使えるのであればコントロールIDを調べれるのでは?

http://madia.world.coocan.jp/cgi-bin/vbnet/wwwlng.cgi?print+200708/07080013.txt
アルウィンドウの子ウィンドウという関係であれば
SendDlgItemMessageを使ってみるとよいでしょう。

編集 削除
大和撫こ  2007-08-21 15:19:21  No: 66055  IP: 192.*.*.*

spyでのハンドルが000108B4
に対し
findwindowexで取得できるハンドルが
67785みたいな感じでBとか文字列が入ってないのもおかしいなぁと
思っていました。

::SendDlgItemMessage(hDlg,textbox1, WM_SETTEXT, 0,(LPARAM)"処理終了です!");
をやってみたんですが、
エラーがでます。
VBのVCにあたるIDってnameだと思うんですが、それを指定すると変な感じになります。完全に違うと思いますが?
どうしたらいいのでしょうか?

編集 削除
Blue  2007-08-21 15:26:40  No: 66056  IP: 192.*.*.*

ですから、Spy++のウィンドウ検索を使ってコントロールIDの値を使ってください。
(ウィンドウ プロパティのダイアログにコントロールIDを示す値が載っています)

編集 削除
大和撫こ  2007-08-21 15:35:33  No: 66057  IP: 192.*.*.*

Blueさんのいうとおり
ウィンドウプロパティのコントロールIDを以下のように
していしましたがエラーがでます。どうしたらいいのですか?
::SendDlgItemMessage(hDlg,0006086C, WM_SETTEXT, 0,(LPARAM)"処理終了です!");

編集 削除
Blue  2007-08-21 15:39:16  No: 66058  IP: 192.*.*.*

>0006086C
16進の値ですので10進になおすか頭に0xを付けてください。
(C言語基礎レベル)

::SendDlgItemMessage(hDlg,0x0006086C, WM_SETTEXT, 0,(LPARAM)"処理終了です!");


それと、
>エラーがでます
はなるべく載せてください。

編集 削除
大和撫こ  2007-08-21 15:53:44  No: 66059  IP: 192.*.*.*

すみません。
HWND hDlg;
::SendDlgItemMessage(hDlg,0x0006086C, WM_SETTEXT, 0,(LPARAM)"処理終了です!");
とやると
Run-Time Check Failure #3 - The variable 'hDlg' is being used without being defined.
というエラーがでます。
結局ハンドルを取得しないといけないのでしょうか?

編集 削除
Blue  2007-08-21 15:56:52  No: 66060  IP: 192.*.*.*

>結局ハンドルを取得しないといけないのでしょうか?
えぇ?なぜ今頃。。。

ハンドルを取得しないとどのウィンドウなのかわかんないですよね?
(コントロールIDは一意ではない。)
VBのアプリのウィンドウハンドルはFindWindowとかで取得してください。

編集 削除
大和撫こ  2007-08-21 16:04:46  No: 66061  IP: 192.*.*.*

取得できれば
SendMessageでよかったのではないのでしょうか?
SendDlgItemMessageだったら取得できなくてもいいから
紹介してくれたのかと思っていました。
結局取得するのだったら
SendMessageの方が短くていいとおもうのですが?
SendDlgItemMessageの利点はなんなんでしょう。
それにコントロールIDってspy++で見たところ毎回変わっているようなんですが。

とりあえず、
WindowsForms10.EDIT.app.0.14fd2b5という不可解なクラス名を指定しても
ハンドルが取得できないのが問題だと思うんですが?

ここを教えて頂けないでしょうか?

編集 削除
Blue  2007-08-21 16:29:11  No: 66062  IP: 192.*.*.*

整理します。

VBのForm→親ウィンドウ・・・(1)
VBのFormの中のTextBox→Formの子ウィンドウ・・・(2)

という関係であるため、(2)のウィンドウハンドルを取得するためには
どうしても(2)のウィンドウハンドルを取得する必要があります。

(1)のウィンドウハンドルはFindWindow(またはFindWindowEx)等で取得します。
このとき必要な情報は「ウィンドウタイトル名」および「クラス名」
です。
ウィンドウのタイトルバーに出る文字が一意であれば、ふつうはこれを指定して取得します。

HWND hWnd;
hWnd = ::FindWindow(NULL, _T("VBのウィンドウタイトル名"));


で、次に子ウィンドウの取得方法ですが、
・EnumChildWindows
・FindWindowEx
・GetDlgItem
等方法があります。
EnumChildWindowsはCALLBACK関数が必要になるので初心者向けではないので
省略します。
下の2は親ウィンドウのウィンドウハンドルから取得します。

FindWindowExの場合、TextBoxの場合クラス名で取得することになります。
ここで同じクラス名のコントロールがいくつもあるとき、FindWindowExは
工夫しなければ使いづらいです。

そこでコントロールIDと呼ばれる一意で普遍な値があるので、
それを使って取得するというのがGetDlgItemです。
# ということで
# >それにコントロールIDってspy++で見たところ毎回変わっているようなんですが。
# は本当なのかなぁと。

よって、コードで書くと

HWND hEdit = ::GetDlgItem(hWnd, 0xXXXXXXX);

と取得できます。
で結局のところSendMessageをhEditに対して使うので通しで書くと

HWND hWnd;
hWnd = ::FindWindow(NULL, _T("VBのウィンドウタイトル名"));
HWND hEdit = ::GetDlgItem(hWnd, 0xXXXXXXX);
::SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)"処理終了です!");

となるわけです。

ここで、私がSendDlgItemMessageを押したのはしたの2行を1行でかけるという点です。

HWND hWnd;
hWnd = ::FindWindow(NULL, _T("VBのウィンドウタイトル名"));
::SendDlgItemMessage(hEdit, 0xXXXXXXXX, WM_SETTEXT, 0, (LPARAM)"処理終了です!");

まぁ、これがいやならSendDlgItemMessageを使わないでいいです。



で、
>WindowsForms10.EDIT.app.0.14fd2b5という不可解なクラス名を指定しても
>ハンドルが取得できないのが問題だと思うんですが?
はどこで指定しているのかによります。
(1)を取得して、(2)を取得するときにFindWindowExの第3引数に指定しているのか?
ってことです。

編集 削除
Blue  2007-08-21 16:29:49  No: 66063  IP: 192.*.*.*

しょっぱな間違えていた...orz

>どうしても(2)のウィンドウハンドルを取得する必要があります。
どうしても(1)のウィンドウハンドルを取得する必要があります。

編集 削除
大和撫こ  2007-08-21 16:51:20  No: 66064  IP: 192.*.*.*

やったあ〜♪♪♪
Blueさんの教えのとおりやったら成功しました〜♪
ここまでくるのに苦節、半日ーーー
ありがとうございました〜♪
解決とさせていただきます!
::GetDlgItemを知らないのが
一番のネックだったみたいですね。
本当にありがとうございました!

編集 削除
荣荣  2008-06-01 21:27:48  No: 66065  IP: 192.*.*.*

看不懂啦

編集 削除