こんにちわ。
VC6(SP5)MFC Windows2000で開発しています。
ある送受信を行うスレッドがありまして、
そこでのログをウィンドウ上のListCtrlに順次表示させたいと思ってます。
スレッドからウィンドウに対してSendMessageやPostMessage?で
通信するにはどのようにすれば良いのでしょうか?
SendMessageの第一引数にハンドルの指定があるので、
ここにウィンドウのハンドル(AfxGetMainWnd()の戻り値?)を
入れてやれば良いとは思うのですが、ではウィンドウ側で
呼ばれる関数はどこでどのように定義すれば良いのかがわかりません。
------------------------------------
余談(上の質問書いてて気になりました。)
また逆にウィンドウ側からスレッドにメッセージを送ることも
可能なのでしょうか?スレッドの動作中にどうやってメッセージ
受け取るのでしょう・・・?
------------------------------------
スレッドの起動時に直接ウィンドウのハンドルを渡して
そこで書く事も出来るとは思うのですが、
スマートなやり方ではないのかな?と思うのと、
スレッドは別の処理をしてるのでウィンドウ側に
通知だけをポンポン投げれば、スレッドは本来の処理に
専念出来ると思って質問した次第です。(考え方あってますか?)
VCでの開発がまだ1ヶ月足らずでMSDNも上手く
読みこなせてない状態です。
初心者向けの参考サイト等でも良いので回答頂ければ幸いです。
稚拙に質問だとは思いますが宜しくお願い致します。
すみません。
自作ではなくユーザー定義で見つかりました。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200004/00040004.txt
一応本題は解決しましたが、
余談の部分の回答頂ければ嬉しいです。
MFC ならば、メッセージマップを作成します。
ここに、どのメッセージのときどのメンバ関数を呼ぶか書きます。
メッセージによってメンバ関数の名前や戻り値引数が決められていて
それに合わせなければいけません。
ON_MESSAGEを調べましょう。
WM_USERじゃなくてWM_APPにしましょう。
ウィンドウのあるスレッド(一般的にGUIスレッドと呼んでいる)も
ウィンドウのないスレッド(一般的にワーカースレッドと呼んでいる)も
長時間処理し続けてメッセージが来ているか確認しない構造になっていれば
メッセージを受け取りませんよ。
基本的にどちらも対等なスレッドです。
--------------------------------------
ワーカースレッドにもメッセージ送れますよ。
隠しウィンドウを使ってもいいし、
ウィンドウハンドルのないスレッド宛PostThreadMessageもあります。
無論、ワーカースレッドが常にメッセージが来ているか確認し、
メッセージが在ったら処理するように作っていなければいけませんけど。
PostThreadMessageの場合
MFCのメッセージマップは使えないので
自分でメッセージループに手を加えることになります。
キャンセルしてくれなどの通知の場合は同期イベントにして
ワーカスレッドのところどころにタイムアウト0でチェックする方法もあるね。
最適化されなければ単なるbool型変数がtrueかfalseで通知してもいいんだけどね。
--------------------------------------
ウィンドウハンドルを渡す方法でいいですよ。
スレッド間で共有して使う情報を構造体にしてポインタを渡してもいい。
その場合マルチスレッドであることに注意しましょう。
PostMessageでぽんぽん通知するといいですね。
処理できないほど大量に送られてもGUIスレッドが困るけど。
SendMessageは相手先でメッセージを処理してくれるのを待つので
ワーカースレッドが待たされますね。
回答ありがとうございます。
wclrpの解説のお陰で、また仕組みが少しわかりました。
ところで、便乗でもう1つ質問なのですが、
私のレスのリンク先のサンプルの通りで動きましたが、
ユーザ定義のメッセージ受信関数(?)の定義を書く位置なのですが、
どこが良いのでしょうか?
<xxxxx.h内>
// インプリメンテーション
protected:
HICON m_hIcon;
// 生成されたメッセージ マップ関数
//{{AFX_MSG(CMailSimDlg)
virtual BOOL OnInitDialog();
~省略~
1.ココ?→afx_msg void OnSendRecvLogWrite(UINT wParam,LONG lParam);
DECLARE_EVENTSINK_MAP()
//}}AFX_MSG
afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);
2.ココ?→afx_msg void OnSendRecvLogWrite(UINT wParam,LONG lParam);
DECLARE_MESSAGE_MAP()
3.ココ?→afx_msg void OnSendRecvLogWrite(UINT wParam,LONG lParam);
(要はどこでも良い?)
1~3のどこでも動くのですが、セオリーと言うか普通はどこに書くのが
一番良いのでしょうか?動けばいいやってのが一番嫌なので知りたいのですが。
DECLARE_EVENTSINK_MAP()やDECLARE_MESSAGE_MAP()といったマクロ関数(?)の
動作なんかも知るべきなのでしょうか?勿論知っておいて損はないと思いますが。
もし宜しければご回答お待ちしておりますm(__)m
VC6なら、
//{{AFX_MSG
から
//}}AFX_MSG
の間に書いておくべきかな。
私は逆に//{{AFX_MSG(XXXX) ~ //}}AFX_MSGの間には入れないようにしてました。
この部分はクラスウイザードが使用すると言う認識でしたので自前で追加した分は
わざと入れないようにしていたと思います。
この辺は、入れても入れなくてもアプリの動作には関係ないと思います。
IDE上での扱いに違いが出る事はあると思いますけれど。
シャノンさんPATIOさんレスありがとうございます。
どこでも動くと言う事で、
やはり人によって色々と見解があるようですね。
自分はPATIOさんと同じ様にAFX_MSGの外に
しようと思います。
回答ありがとうございました。