ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

VC++を極める会?コミュの(MFC)別コントロールで似たような処理をしたいのです。

  • mixiチェック
  • このエントリーをはてなブックマークに追加
こんにちは、悶といいます。
プログラムは楽するために努力する、がモットーです。

自分はVC++6.0 + MFCという環境で開発することが
よくあるのですが、非常にめんどくさいな、と思うことがあります。

【例】-------------------------------------------------
ダイアログベースのプログラム
コントロール:

ボタンA → MFCのCButtonとしてダイアログのメンバにある
ボタンB → CButtonとしてメンバ
エディットボックスA → CEditとしてメンバ
エディットボックスB → CEditとしてメンバ
コンボボックス   → なんかサブクラスされてて
            CMyComboBoxというものでメンバ

スタティックコントロール → CStaticとしてメンバ

-------------------------------------------------------
こんなダイアログがあったとします。今回の問題では、
それぞれのコントロールの機能とかは関係ありません。

たとえば、この状況で、

「このダイアログに張り付いているそれぞれのコントロール
 にマウスがオーバーしたとき、メッセージボックスに
 マウスのあるコントロールの説明文を表示してくれ」

と、言われたとします。
例えば、ボタンAの上をマウスで通過すると、
メッセージボックスが表示されて、
「ボタンAだよ」
というメッセージが表示され、コンボの上を通過すると、
「コンボだよ」
と表示されるイメージです。

ちょっと分かりにくいでしょうか・・要するに、

「コントロールは違えどおんなじメッセージでほぼおんなじ
 動作をさせたい」

というシチュエーションです。ツールチップとかでもありがちですが・・

こんな場合、通常どうやるのが最も楽なのでしょうか?
すべてのコントロールのPretransMessageかなんかを
いちいちオーバーライドさせて実装する・・
それは無いですよね。めんどくさいです。

僕はいろいろ考えた結果、それなりに有効っぽい手段を
思いつきました。

template<class base_wnd>
class CMessageDisplayWnd : public base_wnd {
public :
CMessageDisplayWnd( const char* sz)
: m_strDiscription(sz){}

virtual LRESULT DefWindowProc( UINT..忘れました ) {
switch(message)
{
case WM_MOUSEMOVE :
{
... なんかマウスオーバー判定処理

MessageBox( m_strDiscription );

}
}
}
protected:
CString m_strDiscription;
};

こんな感じでtemplateで継承し、継承したクラスの
ウインドウメッセージ監視仮想関数をオーバーライドし、
任意のメッセージで処理を入れておきます。

でこうした後、たとえばダイアログクラスで

CButton m_ButtonA; // ボタンA

こうなっている部分を、

CMessageDisplayWnd<CButton> m_ButtonA;

こんな感じにします。で、ダイアログのコンストラクタで
: m_ButtonA("ボタンAだよ")

みたいにします。以降他のコントロールも同様に
処理します。

こうすれば似通った処理を一箇所にまとめられてオイシイ
のでは?と興奮しています。色々応用も出来そうだし・・

実はこんなことしなくても、もっと普通にこういった問題に
対処できるのでしょうか?

何かよい知恵を持っている方がいらしたら、よろしく
お願いいたします。

コメント(6)

map<UINT,string> でコントロールIDとチップ文字列の対応表を作っておいて...って手もありそう。
んじゃあ、OnMouseMove上でカーソルの座標と各コントロールの矩形の座標を比較してどのコントロール上にマウスがいるのかいないのかを判別してみれば?これならVisualCあんまりしらない人でも内容わかる。
>アキラさま

>ON_CONTROL_RANGEというマクロ

おお!こんな方法があったのですね!コントロールIDの
管理さえ気をつければ、相当便利そうですね・・
動的にコントロールを作成するときに活躍しそうです。
ありがとうございます。

> επιστημηさま

>map<UINT,string>

これもシンプルで有効そうですね!なんか処理が
複雑になったり、IDごとに微妙に違う動作に
なってきたら stringの部分をクラスにしてしまえば
いいというわけですね。あ、mapを継承してFactoryMethodみた
いなものを追加するとか・・

この方法もいろいろ状況に応じて都合よくやれそうですね。

>やっとし様

OnMouseMoveというのは、

ダイアログクラス::OnMouseMove

でしょうか?僕も最初「とりあえずOnMouseMoveだべ」
と思って入れてみたのですが、コントロールの上を
マウスが移動しているときにはOnMouseMoveがきません・・
OnKeyDownもそうですね。
これって簡単にOnMouseMoveが呼ばれるようにできるんでしょうか・・

僕はその方法がわからず、
「え?全部のコントロールをサブクラスするか、
 CWinApp::ProcessMessageFilterとか使うの・・?
 めんどくさい・・いやまて、よしんばOnMouseMove
 でうまくいったとして、ダイアログ追加で
 他のダイアログクラスで同じ動作を実装する場合、
 同じような記述を複数回行う危険性が・・
 めんどくさい・・」

そうなって上記の方法を考え出したのです。
しかし上記クラスにはいくつか欠陥があり、
特に致命的なのは、

「継承元クラスにデフォルトコンストラクタが無い場合
 は・・特殊化・・って意味無いじゃん」

というものです。

>これならVisualCあんまりしらない人でも内容わかる。

これはとても大事ですよね。やり方がいろいろあるだけに、
最も直感的な実装がベストだと思います。そうなると
僕の考えた方法や ProcessMessageFilterより、OnMouseMove
のほうが、

「あーマウスが動くときはコレをするのか」

というのがすぐ分かり、エレガントだと思います。

>あらぼさん

なるほど、やはりその発想なのですね!関連付けは
やっぱりmapなんかを使うのがいいのでしょうか?

/////////////////////////////
うーんやっぱり色々な方法がありますね・・VCに限らず

「なんか楽をしようとしたらヘンな実装になりそうだ・・
 コレはありなのか?」

ということがよくあります。ナイスな処理とトリッキーな
処理の境目って難しいですよね・・

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

VC++を極める会? 更新情報

VC++を極める会?のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング