度々お世話になっています。よろしくお願いします。
OSはXP-SP2、環境はVC++6.0、SDKで行っています。
先日の質問でProcedure間のデータのやり取りについてお聞きしたんですが、あの時はダ
イアログボックスとのデータのやり取りだったので、SendMessage関数ではなく
DialogBoxParam関数を教えていただきました。
今回は、複数ウィンドウを開きウィンドウ分のProcedureを複数作成し、そのProcedure間
でデータのやり取りを行いたいと思うのですが、SendMessageが一番よいやり方なので
しょうか?
SendMessageを使い、WM_CREATEでProcedure内で定義した変数に送られてきたデータを格
納し、そのデータを使いたいと思いやってみたのですがうまくいきません。
なにかよい方法ありますでしょうか?教えていただければ幸いです。よろしくお願いします。
>SendMessageを使い、WM_CREATEでProcedure内で定義した変数に送られてきたデータを
>格納し、そのデータを使いたいと思いやってみたのですがうまくいきません。
ここの部分が良く分かりません。
Procedure内で定義した変数と言うのはstatic変数か何かですか?
単なるauto変数だとProcedureから抜けた時点で開放されてしまうと思いますけれど。
蛇足ですが、
SendMessageを使った場合はそのメッセージハンドラが終了しないと呼び出し元に
返ってこないので呼び出されたメッセージハンドラからさらにSendMessageしていたりすると
めぐりめぐってループに陥ってデッドロックとかと言うのも考えられないことはないです。
ですから、使用するときはその辺の注意をした方がいいです。
特にどうしてもSendMessageを使わざる得ないような状況でないのなら
PostMessageの方が安全です。
それぞれ適材適所と言うのがあるのでその辺はご注意ください。
PATIOさん、ありがとうございます。
>Procedure内で定義した変数と言うのはstatic変数か何かですか?
はい!そうです。Procedure内でstatic変数定義し、WM_CREATEでメッセージを受け取り
WM_COMMANDなどの他のメッセージで受け取ったデータを使いたいなと思っています。
GetMessageを使うか使わないかが違うだけで、基本的にPostMessageとSendMessageの使い
方は同じですよね?PostMessageも一度やってはみたのですが、うまくデータの受け取り
ができず同じ結果になってしまいました。
このようなコードを書いてみました!ただこのコードはWM_CREATEに送るとできなかった
ので直接WM_COMMANDのIDM_1に送りました。どうでしょうか?
WindowProcedure1()
{
:
:
hWnd_2=CreateWindow( 略 );
PostMessage(hWnd_2,WM_COMMAND,IDM_1,iNumberOfHits);
// iNumberOfHits:送りたいデータ
}
WindowProcedure2()
{
static int iNumber;
switch () {
case WM_CREATE:
:
:
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDM_1:
{
char Temp[256];
MSG lpMessage;
PeekMessage(&lpMessage,hWnd_2,0,0,PM_REMOVE);
iNumber=(int)lpMessage.lParam;
:
:
}
break;
}
}
break;
}
PostMessageとSendMessageには大きな違いがありますよ。
それをきちんと理解して使わないとハマル原因になります。
違わないなんて事はありません。
もし理解できていないのであれば、きちんと確認される事をお勧めします。
ウインドウプロシジャはメッセージの受信を行った後呼び出されるはずなので
ウインドウプロシジャの中でPeekMessageする必要はないのでは?
WM_COMMANDで呼び出されたときにLPARAMとして受信できていると思いますけれど。
どうもウインドウメッセージのやり取りに関する理解が不正確だと思います。
デバッガ等でこの辺の流れがどうなっているのかをきちんと確認してください。
あと、各処理の中で各パラメータがきちんと受け取れているかを確認した方が
良いです。
WM_CREATEで受け取れていないと書いていますが、実際には受け取り方に問題が
あるだけではないでしょうか。
WM_CREATEのWPARAMとLPARAMにどんな物が設定されてくるのかをもう一度確認する
事をお勧めします。LPARAMに直接引き渡した内容が入ってくるわけではないと言うことを
HELPかMSDNで調べて確認してみてください。
ちなみにユーザー定義のメッセージを飛ばしたいのであれば、
WM_COMMANDを使うのではなく、
#define WM_INITDATA_SEND (WM_APP + 1)
と言うようにメッセージIDを起こしてPostMessageした方がいいです。
PostMessage(hWnd_2, WM_INITDATA_SEND, 0, iNumberOfHits);
ヒント:
ちなみに上記のように値渡しが出来る場合はPostMessageでも大丈夫です。
WindowProcedure2()
{
static int iNumber;
switch () {
:
:
case WM_INITDATA_SEND:
iNumber=(int)lParam; // ウインドウプロシジャのLPARAMをそのまま使え
るはず
break;
:
:
基本骨格の部分であるWinMainとウインドウプロシジャ含めたメッセージの流れを
勉強しなおしましょう。
PATIOさん。ありがとうございました。
一応解決しました!
勉強しなおし今後にいかしたいと思います。
WM_APP(0x8000)は将来Windowsが使用するための予約領域で
任意メッセージはWM_USER(0x0400)からではなかったでしょうか?
>WM_APP(0x8000)は将来Windowsが使用するための予約領域で
>任意メッセージはWM_USER(0x0400)からではなかったでしょうか?
違います。
WM_APPはアプリケーション用で、WM_USERはプライベートウィンドウクラス用です。
WM_USERはコントロールによっては、既に使われている部分もありますので、
むやみに使うと衝突します。
>WM_USERはコントロールによっては、既に使われている部分もありますので、
後から追加になった機能を実現するために既に使われています。
grepでWM_USERを使ってVCのヘッダーファイルを探るとごろごろ出て来ます。
例えば、ツールバーコントロールとかレバーコントロールなんかのメッセージにも
使われていますし、既存のコントロールに追加した機能の部分に使われている部分も
あります。
OS2が出始めの頃はWM_USERと言う定義の通り、ユーザー定義メッセージ用だったように
記憶していますが、Windowsではどうだったか記憶が怪しいです。
Windows3.1くらいの頃は定義名の通りだったかもしれません。
現在ではREEさんが言われている通りの状況なのでWM_APPから使った方が無難です。
私が普段使用しているリファレンスには
0x8000~0xBFFF Windowsが将来使用するために予約されています。
と書かれていたので、今までコントロールとの衝突に気をつけながら、WM_USERを使用し
ていました。
今、MSDNで確認にてWM_APPを使用してよいことを確認しました。
勉強させさせていただき、ありがとうございます。