SendMessageについて

解決


かかし  2011-02-03 18:54:30  No: 72308  IP: [192.*.*.*]

お世話になります。

現在、VS2005  MFCにてダイアログベースのアプリを作成しています。

アプリA.EXEとアプリB.EXE間でSendMessageを用いてプロセス間通信
を行いたいのですがFindWindow()にてウィンドウタイトルから送受信先の
ハンドルを取得しているのですが取得できません。
FindWindow()の使い方がわかりません。ご教授頂けないでしょうか。
ちなみに、ウィンドウタイトルはダイアログのキャプション名を指定しいます。

以下が送信側のコードです。
HWND            recv_wind1,recv_wind2;
WPARAM          wParam;
LPARAM          lParam;
COPYDATASTRUCT  cds;

CHAR lpszData[] = "This is TEST.";

    
cds.dwData = 1;
cds.cbData = sizeof(lpszData);
cds.lpData = (LPVOID)lpszData;

recv_wind1 = ::FindWindow(NULL, (LPCTSTR)_T("MessageSendTest"));
recv_wind2 = ::FindWindow(NULL, (LPCTSTR)_T("NCE_Analysis_Tool"));
   
wParam = (WPARAM)recv_wind1;  //送信側のウィンドウハンドラ
lParam = (LPARAM)&cds;    //送信するデータ

::SendMessage( recv_wind2, WM_COPYDATA, wParam, lParam );

宜しくお願い致します。

編集 削除
仲澤@失業者  2011-02-03 20:34:23  No: 72309  IP: [192.*.*.*]

>アプリA.EXEとアプリB.EXE間でSendMessageを用いてプロセス間通信
>を行いたいのですがFindWindow()にてウィンドウタイトルから送受信先の

SendMessage()では安全なデータ転送はできないものと思ってください。
従って、本件のアイデア自体がやや誤りであると言えます。
ただし、ロックしたグローバルメモリを渡す方法など、プロセスや
スレッドから独立した資源をやり取りする場合は可能となります。
んが、この方法は、クリップボード経由のデータ転送と、原理的に
同じです。クリップボードのほうがましというわけです。

編集 削除
YuO  2011-02-04 11:50:30  No: 72310  IP: [192.*.*.*]

FindWindowで取れないということは,何らかの間違い (タイトルが間違っている等) があるのでしょう。
::GetLastErrorでエラー情報を取得してみてはどうでしょう。

> SendMessage()では安全なデータ転送はできないものと思ってください。
そうなのですか?
WM_COPYDATAを正しく使う限り,問題はないと思っていましたが。
何が問題になるのか,教えて頂けないでしょうか。

編集 削除
ロマ  2011-02-04 12:35:27  No: 72311  IP: [192.*.*.*]

FindWindowが成功しているかどうか確認してみてください
(FindWindowの引数のキャプションと戻り値のHWNDと
Spy++で調べたキャプションとHWNDが等しいかどうか)。

あと、WM_COPYDATAのWPARAMに入れた送信側ウィンドウのスレッドと
提示されたコードの実行スレッドが違う場合に、
うまくいくのかどうか、不安な感じがします。
WM_COPYDATAをウィンドウのスレッドで試してみてください。

> SendMessage()では安全なデータ転送はできないものと思ってください。

この話は初耳です。よろしければ、解説いただけると幸いです。
ちなみに、私はクリップボードを汚したくないので、
CUT,COPY以外では、クリップボードは使っていません。

編集 削除
ロマ  2011-02-04 12:37:57  No: 72312  IP: [192.*.*.*]

かぶった、すみません。

編集 削除
仲澤@失業者  2011-02-04 15:26:54  No: 72313  IP: [192.*.*.*]

WM_COPYDATAについては過去に一二度「同一プロセス」内で
使ったことしかないのでコメントしませんでした。
WM_COPYDATAの説明には明確には記述されていませんが、
おそらく渡されたデータを一度プロセスから独立のメモリー
にコピーしてから渡しているのでしょう。
この場合プロセスやスレッドをまたいでも正しくデータが
渡されると考えられます。

編集 削除
かかし  2011-02-04 16:09:13  No: 72314  IP: [192.*.*.*]

お世話になります。

recv_wind1 = ::FindWindow(NULL, _T("MessageSendTest"));
err = ::GetLastError();
recv_wind2 = ::FindWindow(NULL, _T("NCE_Analysis_Tool"));
err = ::GetLastError();

GetLastErrorではエラーになっていませんでした。0が帰ってきます。
また、Spy++で調べたHWNDとFindWindowで取得したHWNDは一致しています。
但し、ステップ実行で確認すると「recv_wind1はunusedでCXX00300:エラーです。:式を評価できませんなっています。」となる場合があります。

あと、SendMessageできるか確認したんですが(OnCopyData()が呼ばれました)、自分自身(recv_wind1)には送信できますがrecv_wind2には送信できませんでした。

よろしくお願い致します。

編集 削除
ロマ  2011-02-04 19:48:02  No: 72315  IP: [192.*.*.*]

> ::SendMessage( recv_wind2, WM_COPYDATA, wParam, lParam );
SendMessageを呼ぶスレッドとWPARAMの値(recv_wind1)のスレッドが
等しい場合と異なる場合を試してみましたが、
どちらも問題なく転送できました。

そちらでうまくない理由が思い浮かびません。
#「recv_wind1はunused」これ、気になります。

編集 削除
かかし  2011-02-04 21:41:54  No: 72316  IP: [192.*.*.*]

お世話になります。

初歩的なミスでした。

OnCopyData()をメインダイアログではなく、サブダイアログで
行っていました。SendMessageはメインダイアログに対してでした。
メインダイアログでOnCopyData()することでメッセージを受信できました。

お手数をお掛けしました。

編集 削除