スレッドからのメッセージについて。

解決


ぬる  2005-03-28 22:28:43  No: 56801  IP: [192.*.*.*]

お世話になります。W2K+VC6でスレッド&ソケットの勉強しています。
Dlg上でボタンを押すことにより、スレッドが起動して通信を開始する
アプリを作ってます。画面上に現在の通信状態を表示したいと思い、
状態表示用のEditBoxとProgressBarを付けたのですが、スレッド側から
Dlg側への情報の受け渡し方法がわかりません。
SendMessageを使うのが一般的だと思うのですが間違ってますか?
以下、かいつまんでソースです。
-----------------------------
#define WM_TESTMSG WM_APP+1 // メッセージ定義

<<TestDlg.cpp>>
// メッセージマップ内
ON_MESSAGE( WM_TESTMSG , RcvMsg)

//CreateThreadで呼ばれる通信を行う関数
void WINAPI NetWorkTest(CTestDlg *objDlg)
{
    CTestSock objSock;
    objSock.StartUp();
    //↑MFCのクラスを使わず自作のクラスで通信やってます。
}

//
LRESULT RcvMsg(WPARAM wParam, LPARAM lParam)
{
      MessageBox("テスト");
      return 0;
}

<<TestSock.cpp>>
int CTestSock::StartUp()
{
   「ここでメッセージを送ってRcvMsg()に飛びたい。」
}
---------------------------------------
分かりにくくて申し訳ありませんが、
何卒宜しくお願い致しますm(__)m

編集    削除
シャノン  2005-03-29 00:53:15  No: 56802  IP: [192.*.*.*]

> スレッド側から
> Dlg側への情報の受け渡し方法がわかりません。
> SendMessageを使うのが一般的だと思うのですが間違ってますか?

おっしゃるとおり、SendMessage を使うのが一般的ですが、そこまでわかっていて、何がわからないのでしょうか?
SendMessage の使い方でしょうか?

編集    削除
ぬる  2005-03-29 02:30:43  No: 56803  IP: [192.*.*.*]

すいません。よくよくソースを見たら、
メインスレッド側で、ワーカースレッドの状況を取得しようとしていて
whileで無限ループしてまして、sendmessageが受けられなかった様です。

一応上手く出来たようなのですが、便乗で1つ質問させてください。

>SendMessage の使い方でしょうか?
これなのですがMSDNを見ると
CWindow::SendMessageとAPIのSendMessageとありますが、
前者には引数(HWND hWnd)が不要です。
この違いがイマイチ分からないのですが、どう言った場合に使い分ければ
良いのでしょうか?

今回ワーカースレッドにDlgのポインタを渡して、「SendMessage(*objDlg,
 WM_TESTMSG, 0, 0)」としました。仮に*objDlgと取ってしまうと、
不正な・・・のエラーが出ます。

単純に自分自身に対するメッセージと別の相手に対するメッセージの場合で
宛先を指定する/しないと言うだけの違いで良いのでしょうか?
予想するに、↑の例だと、ワーカースレッドはMSGを受けられない為、
MSGを受けられるオブジェクトを指定しろって事でエラーになっているのだと
認識しているのですがあってますか?

ちょっとズレてしまいましたが、回答頂けると嬉しいです。
問題の件は解決とします。ありがとうございました。

編集    削除
ゥ・  2005-03-29 03:20:59  No: 56804  IP: [192.*.*.*]

CWindow::SendMessageは、ウィンドウハンドルを極薄くラップしたATLのクラスCWindowのメンバ関数です。
CWindowオブジェクト内にあるウィンドウハンドルを第1引数にAPIのSendMessageを呼びます。

編集    削除
シャノン  2005-03-29 05:40:11  No: 56805  IP: [192.*.*.*]

> 今回ワーカースレッドにDlgのポインタを渡して、「SendMessage(*objDlg,
 WM_TESTMSG, 0, 0)」としました。仮に*objDlgと取ってしまうと、
不正な・・・のエラーが出ます。

この場合、SendMessage に渡しているのは何でしょうか?
objDlg がポインタならば、*objDlg は CTestDlg の実体ですね。
SendMessage の第一引数は HWND で、CTestDlg を渡すことは出来ませんが、CWindow に定義されている、operator HWND() によって、自動的に HWND にキャストされて、実際にはウィンドウハンドルが渡されています。

ATL ではどうだか知りませんが、MFC では、CWnd などのオブジェクトは、その情報をスレッドごとに固有の TLS という領域に保持しています。
このため、CWnd オブジェクト自体を別のスレッドに渡すと、渡された先のスレッドの TLS の内容は、そのオブジェクトが意図していたものとは違いますから、エラーが出てしまいます。
このため、CWnd オブジェクトを他のスレッドに渡す際には、HWND を渡すことが義務付けられています。
ATL でも、これは同じことなんでしょうかね。

編集    削除
超初心者  2005-04-28 16:36:27  No: 56806  IP: [192.*.*.*]

> 今回ワーカースレッドにDlgのポインタを渡して、「SendMessage(*objDlg,
>  WM_TESTMSG, 0, 0)」としました。仮に*objDlgと取ってしまうと、
> 不正な・・・のエラーが出ます。

それって、
SendMessage(*objDlg, WM_TESTMSG, 0, 0)
は動作したが、
SendMessage(WM_TESTMSG, 0, 0)
が不正な・・・になったってこと?
CTestSockがウィンドウクラスであるがウィンドウは作っていないっていうのなら起きる気がする。
これは、CTestSockのウィンドウへメッセージを送ろうとしてCTestSockのウィンドウが存在しないのだから。
CTestSockがウィンドウクラスでないなら::SendMessageと言うことになるので、引数が違うからコンパイルエラーでそもそも実行できないから不正な・・・にならんよね。

CWindow::SendMessageは、CWindowのメンバ関数からしか使えない。
その(自分)CWindowオブジェクト(インスタンス)のメンバのm_hWndを使います。
だから指定不要。

別のオブジェクトのCWindow::SendMessageを使いたいなら、
objDlg->SendMessage(messsage,lparam,wparam);
です。さてはオブジェクト指向に慣れてないな。
または::SendMessageを使うなら
::SendMessage(objDlg->m_hWnd,messsage,lparam,wparam);
です。

編集    削除