こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

ウィンドウプロシージャの書き方について

VC++Expressで開発しています。

このたびWin32APIを使用してみたいと思い以下のようなマウスの座標を常に表示するプログラムを書いてみました。

Form1.h
-----------------------------------------------
#pragma once
#include <Windows.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")

//(略)

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)
{
switch(msg)
{
case WM_TIMER:
switch(wp)
{
case 1:
POINT point;
GetCursorPos(&point);
label2->Text="X:"+point.x;
label3->Text="Y:"+point.y;
break;
}
default:
return DefWindowProc(hwnd,msg,wp,lp);
break;
}
}

private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
HWND hmyWnd = static_cast<HWND>(this->Handle.ToPointer());
SetTimer(hmyWnd,1,100,NULL);
}
-----------------------------------------------

コレを実行してみると
warning C4441: '__stdcall ' の呼び出し規約が無視されました。代わりに、'__clrcall ' を使用しました
という警告が出た後、ウィンドウが表示されますがラベルの内容は変化しません。

そこで質問させてください。
まず、この様な警告が出る理由はなんでしょうか?
私はウィンドウプロシージャの使い方が間違っていると思うのですが、それより先は調べることが出来ませんでした。

次に前述の疑問に関連してですが、「イベント駆動型のプログラムを書く際はメッセージキューにたまったメッセージをそれぞれ適切なウィンドウプロシージャへ送る」と言う風に理解しているのですが、どのサイトでプログラム例を見てもLRESULT CALLBACK WndProc(略)という受け取る側の関数を書いているだけで、肝心の送る側の関数を記述していません。
そのため、私も見よう見真似で受け取る側の関数だけ書いたのですが、これではもちろんどこに書かれているかも分からない送り側の関数と関連付けは出来ませんよね?
実際にウィンドウプロシージャやその他メッセージ処理ではどのようにして関連付けを行っているのですか?

また、私はプロジェクトを作成したときに最初に出てきたForm1.hと言うファイルにコードを書き込んでいるのですが、これは後々問題になるでしょうか?

少しまとまりの無い質問となってしまいましたが、どうかお答えください。
お願いしますm(_ _)m

投稿日時 - 2012-06-22 23:04:52

QNo.7549273

すぐに回答ほしいです

質問者が選んだベストアンサー

C++/CLIは触っていないのであれですが……。
# 最近はC#いぢってますけど。

>まずは、フォームアプリケーションの場合であってもWin32と同様にメッセージループや送信側のコードを書くのでしょうか?

クラスライブラリ内で処理しているので、コード作成者が書く必要は無い…かと。
コード作成者が必要とする場合はイベントハンドラ登録してコールしてもらうことになります。
# フォームのデバイン画面でイベントハンドラの登録とかできますよね?

>また、送信側と受信側の関連付けについてですが、私はForm::WndProc(m);の部分がwc.lpfnWndProc= WndProc;に対応していると感じたのですが、実際はどうでしょうか?
この場合ですと関連付けを受信側のコードで行っているので、最初にこの関数を呼び出すときにどうやっているのか疑問です。

こちらもクラスライブラリ内でよろしくやってくれている。
と……。

Win32APIレベルで考えると…フォームのウィンドゥを作成したときに本来のウィンドゥプロシージャを呼び出す前にForm::WndProcを実行してくれている。
と考えてよいのではないですかね。
# 処理しなかったメッセージは本来のプロシージャで処理する。

>また、フォーム作成時に関連付けをしないという事はフォームクラスが複数ある時はどうやっているのかも疑問です。

インスタンスが複数…でいいんでしょうかね?
そこらヘンは隠蔽されているHWNDでよろしく処理を振り分けている。
とうことかと。

投稿日時 - 2012-06-23 14:23:01

お礼

>クラスライブラリ内で処理しているので、コード作成者が書く必要は無い…かと。

なるほど、クラスライブラリ内に記述してあるのですね!!
確かにそちらの方が合理的ですね。
実際にご指摘頂いた点を修正し、正しくメッセージを受け取ることが出来ました。

このたびは追加質問にまで答えていただき本当にありがとうございました。
まだまだ、分からないことが多く頻繁に質問させていただくとは思いますが、その時はまたよろしくお願いします。

投稿日時 - 2012-06-24 12:22:43

ANo.2

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

>まず、この様な警告が出る理由はなんでしょうか?

プロジェクトの設定が Win32 アプリケーションではなく、Windows フォームアプリケーション ( C++/CLI アプリケーション ) になっているからではないでしょうか。


>実際にウィンドウプロシージャやその他メッセージ処理ではどのようにして関連付けを行っているのですか?

Win32 アプリケーションでは、RegisterClassEx ウィンドウクラスを登録するときに指定します。

参考ページ
http://www.geocities.jp/ky_webid/win32c/002.html

Windows フォームアプリケーションの場合は、Form クラスの WndProc をオーバーライドして

protected:
virtual void WndProc(System::Windows::Forms::Message %m) override
{
switch( m.Msg )
{
case WM_TIMER:
・・・
break;

default:
・・・
break;

}
Form::WndProc(m);
}

のようなことをしてやればよいと思います。

http://msdn.microsoft.com/ja-jp/library/system.windows.forms.form.wndproc.aspx

投稿日時 - 2012-06-23 03:02:05

補足

回答ありがとうございます。
確かにフォームアプリケーションではなくWin32アプリケーションでつくり直したらWimMainという関数があり、その中でLRESULT CALLBACK WndProcが自動的に生成されていることが確認できました。さらにwc.lpfnWndProc= WndProc;という文でウィンドウとウィンドウプロシージャの関連付けも確認することが出来、非常にすっきりしました。

また、WinMain関数の最後にはメッセージループもあり、その中で送信側のコードDispatchMessage(&msg);も確認できました。個人的にはマイコンでの製作をした経験があり、このメッセージループはそれに共通する考え方だと感じ、非常に満足しています。

本当にありがとうございます。

さて、最後にフォームアプリケーションでの実装についていくつか重ねて質問させてください。
まずは、フォームアプリケーションの場合であってもWin32と同様にメッセージループや送信側のコードを書くのでしょうか?
やはり、送信側のコードが無ければ機能しないという事は想像できるのですが、どのサイトでもそこらへんの説明がされていなくmain関数内でメッセージループを作成している例を見たことが無いため確信できずにいます。

また、送信側と受信側の関連付けについてですが、私はForm::WndProc(m);の部分がwc.lpfnWndProc= WndProc;に対応していると感じたのですが、実際はどうでしょうか?
この場合ですと関連付けを受信側のコードで行っているので、最初にこの関数を呼び出すときにどうやっているのか疑問です。
また、フォーム作成時に関連付けをしないという事はフォームクラスが複数ある時はどうやっているのかも疑問です。


本当はもう少し自分でコードを書いてから質問するべきなのですが、私情により今日はこれからコードをいじれなくなるので先に気になったことを質問させていただきたいと思います。ご了承ください。

とても長くなってしまいましたが。
一つでも返答いただければ幸いです。

投稿日時 - 2012-06-23 11:44:34

あなたにオススメの質問