本ページは公開が終了した情報の複製であり、掲載時点での情報です。本ページに記載されている内容について各所に問い合わせることはご遠慮下さい。
サポート技術情報

[MSVC] MFCを使用しての動的サブクラス化

文書番号: 403856

最終更新日: 1999/03/19


この資料は以下の製品について記述したものです。


この記事は、以前は次の ID で公開されていました: JP403856

概要

この資料は MFC を使用しての動的サブクラス化の一例を紹介したものです。

詳細

<QUESTION>

ダイアログ上で数値しか入力できないエディットコントロールを作成しようとして
CEdit の派生クラスを作成したのですが、それは AppStudio で使用できません。
現状は座標を計算して Create() を呼び出しています。もっと簡単な方法はあ
りませんか?

<ANSWER>

MFC の機能には各コントロールのリソース ID を元に、プログラム実行時にそれを
サブクラス化する手法があります。これを動的サブクラス化と呼んでいます。
基本的な手順は以下の通りです。
  • AppStudio で元になるコントロールをそのままダイアログに貼り付け、普通にリ ソースを作成する。
  • サブクラス化したいクラスの派生クラスを記述する。
  • ダイアログのクラスの中に、メンバとして上記の派生クラスのオブジェクトと、 派生元の既存のコールバック関数を保存する領域( WNDCLASS 型の変数)を宣言 する。
  • ダイアログで CWnd::GetSuperWndProcAddr() をオーバーライドし、その戻り値 として、先程定義したコールバック関数の変数へのポインタを返すようにしてお く。
  • ダイアログの OnInitDialog() の中で サブクラスとなる派生クラスのメンバとし て CWnd::SubclassDlgItem() を呼び出す。パラメータには派生元のコントロール の ID とダイアログのポインタ( this )を渡す。
以下にソースの例を示します。
  /*** 数値しか入力できないエディットコントロール ***/
  class CNumEdit : public CEdit {
          :
          afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
          :
  };
  /** 数値しか入力できないようにする処理 **/
  void CNumEdit :: OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  {
          // 数値以外のキーが押されたら警告音を鳴らす
          if( (nChar >= '0' && nChar <= '9') || nChar == VK_BACK )
                  CEdit::OnChar(nChar, nRepCnt, nFlags);
          else
                  MessageBeep( -1 );
  }
  /*** サブクラス化の対象となるエディットコントロールがあるダイアログ ***/
  class CMyDialog : public CDialog {
          :
          CNumEdit myEdit; // サブクラス化エディットコントロール
          WNDPROC oldEditProc; // 以前の CEdit のコールバック関数を格納する場所
          WNDPROC* GetSuperWndProcAddr(); // オーバーライドする
          :
          virtual BOOL OnInitDialog();
          :
  };
  /** GetSuperWndProcAddr のオーバーライド ***/
  WNDPROC* CMyDialog :: GetSuperWndProcAddr( void )
  {
          return &oldEditProc; // これによって CEdit のデフォルトのコールバッ
                               // ク関数が oldEditProc に保存される
  }
  /** 実際のサブクラス化 **/
  BOOL CMyDialog :: OnInitDialog( void )
  {
          CDialog::OnInitDialog();
          // 以下の処理で ID が示すコントロールが自分の派生元のクラスとなる
          myEdit.SubclassDlgItem(IDC_EDIT1, this);
          return TRUE;
  }
※ウィンドウをサブクラス化する場合は SubclassDlgItem() ではなく
SubclassWindow() を使用します。手順は同じです。
また、CDialog::DoDataExchange() で DDX を使用してエディットコントロールの
オブジェクトを作成し、それを自分が作成したエディットコントロールの派生
クラスのそれに置き代える方法も簡単です。
  /*** ダイアログのクラス ***/
  CMyDialog : public CDialog {
          :
          CNumEdit myEdit; // 派生クラスのオブジェクト
          :
  };
  /*** DDX 部分 ***/
  void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  {
          CDialog::DoDataExchange(pDX);
          //{{AFX_DATA_MAP(CAboutDlg)
          DDX_Control(pDX, IDC_EDIT1, myEdit); // myEdit の部分は CEdit のオブジ
                                               // ェクトであったのを書き換えた
          //}}AFX_DATA_MAP
  }

詳細

  • Visual C++ は、米国 Microsoft Corporation の商標です。

Keywords: KBHOWTO VC10 VC15 VC20 KB403856
Technology: kbAudDeveloper kbvc150 kbVC32bitSearch kbVCsearch

inserted by FC2 system