WM_COPYDATAを用いたプロセス間通信について

[戻る]
PON 2006/07/10(月) 11:05:07
[環境]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すら動作しません。。。
どなたか、お分かりの方、ご返信よろしくお願いします。

 

επιστημη 2006/07/10(月) 11:47:23
SendMessage時、WPARAM,LPARAMを(0ではない)ちゃんとした値を設定してもダメですか?

Ban 2006/07/10(月) 11:51:31
確認ですが、OnCopyDataはどうやって追加されましたか。
直接、何かからのコピペですか。MESSAGE_MAPには正しく追加されていますか。

PON 2006/07/10(月) 12:35:59
[[解決]]
επιστημηさん
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

どうもありがとうございました!!

Blue 2006/07/10(月) 12:53:43
> wParam = (WPARAM)recv_wind1;   //送信側のウィンドウハンドラ
は自分自身なら、this->GetSafeHwnd(); でウィンドウハンドルが取れます。

私も試しにやってみたんですが、mes_recv側に実験用にボタンを作って、

this->SendMessage( WM_COPYDATA, 0L, 0L );

と記述して、きちんとOnCopyDataが呼ばれていたので、LPARAMは関係ないのかなぁと
思っていました。WM_COPYDATAのヘルプを再度確認してみなければならなそうです。


ところで
> ダイアログベースではなくシングルドキュメントだと、findWindowすら動作しませ
ん。。。
こちらはその後どうなりましたか?

PON 2006/07/10(月) 18:01:06
>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だとなんかわかんない名前をつけないと駄目なんでしょうか、、


以上、ご報告まで。

REE 2006/07/10(月) 19:09:46
>SDIだとなんかわかんない名前をつけないと駄目なんでしょうか、、

ウインドウタイトルで検索しているのですからですね。
無題の部分は、開いているドキュメントのファイル名になっています。
(つまり、ファイルを開けば名前も変わります)

SDIでも(MFC正規の方法で)ウインドウタイトルを変更すればよいでしょう。


また、FindWindowを使わないで、ウィンドウハンドルを取得する方法もあります。

古いスレッドには追加発言できません。