• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:   ダイアログのクラス化で仮想関数を用いて派生クラスにしているんです)

ダイアログのクラス化で派生クラスに仮想関数を使用する方法

このQ&Aのポイント
  • ダイアログを基本クラスで静的プロシージャと派生クラスでオーバーライドしてプロシージャを使用する方法について説明します。
  • SetWindowLong関数を使用してポインタを設定する方法と、GetWindowLong関数を使用してポインタを取得する方法を紹介します。
  • WM_INITDIALOGでのポインタの取得に関する問題についても取り上げ、解決策を提案します。

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

  • ベストアンサー
回答No.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; }

dotneer
質問者

お礼

詳しく調べてくれてとても感謝しています。 静的プロシージャから動的プロシージャを呼び出すことはできているみたいです。(なぜかはまだ分からないのですが詳しく調べてみます。) CreateDialogParamといった関数でlParamに値を渡せば可能だとわかりました。 >しかし、まーよくこんなトリッキーなコードが思いつくものだ。。。 全くです。ネットで調べて苦戦していました。 沢山のご回答を貰ったお陰でなんとかなりました。 ありがとうございます。

その他の回答 (4)

回答No.4

 こんにちは。  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;  とすれば取り出せるの筈です。 

dotneer
質問者

お礼

回答ありがとうございます。 どうやらダイアログボックスだとlParamをキャストすれば値が入るようです。

dotneer
質問者

補足

  これで一回試したのですが、そもそもlParamの値が0なんです。 これでは何をやってもダメなのは納得したんですが、lParamの値が0の状態のようです。 DialogBox()の引数に静的プロシージャである、CallProcを指定しているのですが、これがいけないんでしょうか?

  • reset_cat
  • ベストアンサー率68% (94/138)
回答No.3

質問とは関係ないかもしれませんが・・・ ダイアログボックスのウィンドウプロシージャにするのなら、デフォルト処理ではDefWindowProcを呼び出してはならないのでは?

dotneer
質問者

補足

そうですね。 ダイアログ用のプロシージャならBOOL型にすべきなのでそうします。 これはウィンドウプロシージャのクラス化(継承可能)なソースをそのまま 転載したものなんです。

回答No.2

メッセージが WM_INITDIALOG の時に lParam が LPCREATESTRUCT なんですか? WM_CREATE ではなくて?

dotneer
質問者

補足

ダイアログプロシージャを作りたいため、WM_INITDIALOGに変更しました。 しかしWM_INITDIALOGでlParamが自分が得たい値になっているかというと疑問なんです。 というか実際アクセス違反になりました。 どうやったらアドレスを得られるかその方法が分からないでいます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

Set/GetWindowLong よりも Set/GetWindowLongPtr の方が安全だとは思うけど, それはさておきそもそも SetWindowLong は成功しているのでしょうか?

dotneer
質問者

補足

SetWindowLongを直接呼ぶとthisポインタのせいでエラーがでます。 GetWindowLongからは値は0のままなので、その後からthisPtr->SetWindowというふうに しても変化はないです。

関連するQ&A