- ベストアンサー
ダイアログのクラス化で派生クラスに仮想関数を使用する方法
- ダイアログを基本クラスで静的プロシージャと派生クラスでオーバーライドしてプロシージャを使用する方法について説明します。
- SetWindowLong関数を使用してポインタを設定する方法と、GetWindowLong関数を使用してポインタを取得する方法を紹介します。
- WM_INITDIALOGでのポインタの取得に関する問題についても取り上げ、解決策を提案します。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
クラス設計において、あまり静的プロシージャを使ったことが無かった為、調べるのに時間が掛かりました。 静的プロシージャ(CallProc)から静的でないプロシージャ(SetPointer)は呼び出せないのではないかと思い、VCで以下の検証プログラムを組んでみました。 しかし、VC環境で動くことを確認しました。 まず、DialogBox関数ではWM_INITDIALOG時にlParamを渡すことはできなさそうです。 試したわけではありませんが、以下のソースコードをベースにするとmain関数の中で以下のようにする必要があるのでは? ※CBaseを継承したクラスのインスタンスを生成して、そのインスタンスのアドレスを渡す。 CreateDialogParam( hInstance, "Template", hWndParent, (WNDPROC)CBase::CallProc, &dbobj ); しかし、まーよくこんなトリッキーなコードが思いつくものだ。。。 ●検証プログラム #include <iostream> using namespace std; //**************************** // //**************************** class CBase { private: public: static void gofnc(void *obj) { ((CBase*)obj)->func(); } virtual void func() { } }; //**************************** // //**************************** class CDBox : public CBase { private: public: void func() { cout << "message01" << "moji" << endl; } }; //**************************** // //**************************** int main() { CDBox dbobj; CBase::gofnc(&dbobj); getchar(); return 0; }
その他の回答 (4)
- machongola
- ベストアンサー率60% (434/720)
こんにちは。 http://msdn.microsoft.com/ja-jp/library/cc410696.aspx http://msdn.microsoft.com/ja-jp/library/cc410761.aspx http://msdn.microsoft.com/en-us/library/ms645428(VS.85).aspx WM_INITDIALOGのlParamは、CreateDialogParam()/DialogBoxParam()等のLPARAMに指定した値が、其のまま伝わって来るのですから、 if( message == WM_INITDIALOG ) thisPtr = (CBaseWnd*)lParam; とすれば取り出せるの筈です。
お礼
回答ありがとうございます。 どうやらダイアログボックスだとlParamをキャストすれば値が入るようです。
補足
これで一回試したのですが、そもそもlParamの値が0なんです。 これでは何をやってもダメなのは納得したんですが、lParamの値が0の状態のようです。 DialogBox()の引数に静的プロシージャである、CallProcを指定しているのですが、これがいけないんでしょうか?
- reset_cat
- ベストアンサー率68% (94/138)
質問とは関係ないかもしれませんが・・・ ダイアログボックスのウィンドウプロシージャにするのなら、デフォルト処理ではDefWindowProcを呼び出してはならないのでは?
補足
そうですね。 ダイアログ用のプロシージャならBOOL型にすべきなのでそうします。 これはウィンドウプロシージャのクラス化(継承可能)なソースをそのまま 転載したものなんです。
- m-take0220
- ベストアンサー率61% (480/785)
メッセージが WM_INITDIALOG の時に lParam が LPCREATESTRUCT なんですか? WM_CREATE ではなくて?
補足
ダイアログプロシージャを作りたいため、WM_INITDIALOGに変更しました。 しかしWM_INITDIALOGでlParamが自分が得たい値になっているかというと疑問なんです。 というか実際アクセス違反になりました。 どうやったらアドレスを得られるかその方法が分からないでいます。
- Tacosan
- ベストアンサー率23% (3656/15482)
Set/GetWindowLong よりも Set/GetWindowLongPtr の方が安全だとは思うけど, それはさておきそもそも SetWindowLong は成功しているのでしょうか?
補足
SetWindowLongを直接呼ぶとthisポインタのせいでエラーがでます。 GetWindowLongからは値は0のままなので、その後からthisPtr->SetWindowというふうに しても変化はないです。
お礼
詳しく調べてくれてとても感謝しています。 静的プロシージャから動的プロシージャを呼び出すことはできているみたいです。(なぜかはまだ分からないのですが詳しく調べてみます。) CreateDialogParamといった関数でlParamに値を渡せば可能だとわかりました。 >しかし、まーよくこんなトリッキーなコードが思いつくものだ。。。 全くです。ネットで調べて苦戦していました。 沢山のご回答を貰ったお陰でなんとかなりました。 ありがとうございます。