[環境]WinXP Pro / Visual Stdio 2005 VC++
VC++初心者のものです。
過去ログを拝見したのですがうまくいかないので、申し訳ありませんが、
質問させてください。。。
[やりたいこと]
・ダイアログベースで作成した2つのexe間で、SendMessageと
WM_COPYDATAを用いたプロセス間通信
[現在までにしたこと]
●1. VS2005で新規ソリューション(ダイアログベース)を2つ
(送信側mes_send・受信側mes_recv)作成
●2. 送信側mes_sendにはボタンを1つ追加し、そのボタンを押すと、
以下のSendMessageのコードが走るようにする。
void Cmes_sendDlg::OnBnClickedButton1()
{
HWND recv_wind;
recv_wind = ::FindWindow(NULL, (LPCTSTR)_T(mes_recv));
::SendMessage( recv_wind, WM_COPYDATA, 0, 0 );
}
●3. 受信側mes_recvには、Cmes_recvDlgに、WM_COPYDATAのハンドラを追加。
ハンドラ内には、確認用のAfxMessageBoxのみいれておく。
BOOL Cmes_recvDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
AfxMessageBox(_T(Message Recieve));
return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}
●4. 両方の起動をかけて、送信側mes_sendのボタンを押すが、受信側mes_recv
はまったく反応せず。
[デバッグ状況]
■送信側mes_sendのrecv_windの値は、spy++で確認した受信側mes_recvの
ウィンドウ番号が入っている。
-- ウィンドウ 00030D6C 'mes_recv'#32770(ダイアログ)
■受信側mes_recvのAfxMessageBoxでブレークを張って、送信側mes_sendの
ボタンを押しても、ブレークにひっかからない。
状況は以上です。
なお余談ですが、ダイアログベースではなくシングルドキュメントだと、
findWindowすら動作しません。。。
どなたか、お分かりの方、ご返信よろしくお願いします。
SendMessage時、WPARAM,LPARAMを(0ではない)ちゃんとした値を設定してもダメですか?
確認ですが、OnCopyDataはどうやって追加されましたか。
直接、何かからのコピペですか。MESSAGE_MAPには正しく追加されていますか。
επιστημηさん
Banさん
ご返信ありがとうございます!
>Banさん
いえ、コピペではなく、プロパティからハンドラ追加を行いました。
MESSAGE_MAPにも登録されています。
>επιστημηさん
改めてきちんとデータを入れると、うまくいきました!!
void Cmes_sendDlg::OnBnClickedButton1()
{
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(mes_send));
recv_wind2 = ::FindWindow(NULL, (LPCTSTR)_T(mes_recv));
wParam = (WPARAM)recv_wind1; //送信側のウィンドウハンドラ
lParam = (LPARAM)&cds; //送信するデータ
::SendMessage( recv_wind2, WM_COPYDATA, wParam, lParam );
}
としてみたら、うまく動作しました。その後の追試の結果、
***************************************************
●第3引数は0でも動作するが、
第4引数に、必ず何かデータを入れないと、動作しない
***************************************************
としなければ動作しないようです(間違ってるかもしれませんが、、、)
「送るデータが無くてもメッセージは届くだろ」と
安直に考えていた自分のミスです。。。。orz
どうもありがとうございました!!
> wParam = (WPARAM)recv_wind1; //送信側のウィンドウハンドラ
は自分自身なら、this->GetSafeHwnd(); でウィンドウハンドルが取れます。
私も試しにやってみたんですが、mes_recv側に実験用にボタンを作って、
this->SendMessage( WM_COPYDATA, 0L, 0L );
と記述して、きちんとOnCopyDataが呼ばれていたので、LPARAMは関係ないのかなぁと
思っていました。WM_COPYDATAのヘルプを再度確認してみなければならなそうです。
ところで
> ダイアログベースではなくシングルドキュメントだと、findWindowすら動作しませ
ん。。。
こちらはその後どうなりましたか?
>Blueさん
どうも追試ありがとうございます!!
this->GetSafeHwnd();
ってのを使えば、自分のウィンドウハンドル取得できるんですね、、、
でもLPARAM、、、いまいちまだつかめません。。。
> ダイアログベースではなくシングルドキュメントだと、
> findWindowすら動作しません。。。
この件ですが、午後にいろいろ試しまして、少しわかりました。
[ダイアログベースでやった場合]
Spy++で
-- ウィンドウ 00030D6C 'mes_recv'#32770(ダイアログ)
のように表示されたので、findWindowの引数をmes_recvにしていました。
つまり、「なーんだ、ファイル名でウィンドウを探せばいいのか」と
そのときは考えました。
で、
[シングル(SDI)でmes_recvを作った場合]
同じようにSpy++でみると、
-- ウィンドウ 00040A2E '無題 - mes_recv' Afx00400000b:b:00010013:00(以下略)
のように表示されていました。ダイアログのときと違ってわけのわかんない
数字がいっぱいあったのでびっくりしましたが、「きっとダイアログのときと
同じはず」と思い、
recv_wind = ::FindWindow(NULL, (LPCTSTR)_T(mes_recv));
と書いたのですが、どうやってもrecv_windに値が入らない。。。。
で、本日午後、結果的に、
●recv_wind = ::FindWindow(NULL, (LPCTSTR)_T(無題 - mes_recv));
という風に、ファイル名以外の部分も付け加えると、ウィンドウハンドルを
引くことができました。
ダイアログベースのときはファイル名でよかったのに、
SDIだとなんかわかんない名前をつけないと駄目なんでしょうか、、
以上、ご報告まで。
>SDIだとなんかわかんない名前をつけないと駄目なんでしょうか、、
ウインドウタイトルで検索しているのですからですね。
無題の部分は、開いているドキュメントのファイル名になっています。
(つまり、ファイルを開けば名前も変わります)
SDIでも(MFC正規の方法で)ウインドウタイトルを変更すればよいでしょう。
また、FindWindowを使わないで、ウィンドウハンドルを取得する方法もあります。