MFC 〜GetDialogItem()関数〜


 MFCは Microsoft Foundation Class Liblary の略ですが、このページはMFCを使ったことのある人対象です。まず下の文を見て下さい。

    CButton* button;
    button = (CButton*)GetGlgItem( ID_EDIT );

 ID_EDIT はエディットボックスコントロールのリソース ID として、定義されているとします。今まで、僕が、AppWizerd を使ってダイアログにコントロールを貼り付けたとき、そのコントロールに対して処理をしたいときは、そのコントロール型のポインタを宣言し、そのポインタに対して上のような処理をして、例えば、エディットボックスの入力項目を見ていたりしました。ところが上の文章は間違っているそうです。

 確かに、上のコードでもうまくいきます。事実、僕は今まで上のやり方でプログラムを作っていたし、そのプログラムは期待した通りに動いていました。「どこが悪いのだ!」って、思われる方もおられると思います。僕も詳しいことは分かりませんが、分かる範囲で説明したいと思います。

 GetGlgItem 関数は CWnd 型のポインタを返す関数です。そのポインタを CButton ポインタ型にキャストしていますが、CButton 型は CWnd 型の派生クラスです。即ち、親クラス型のポインタを子クラス型ポインタにキャストしているわけですが、ここがまずいわけです。子クラスである CButton が多重継承をされているとしたら、あいまいさが生じやすくなります。そのほか、仮想基本クラスを使っている時なども同様のようですが、はっきり言って、この辺のことには詳しくないわけで、このくらいにしておきます。

 で、解決法ですが、2つほど紹介したいと思います。まずは、ClassWizerd を使っている場合、ClassWizerd 画面のメンバ変数タグで使いたいコントロールを、張り付けた(例えば CDialo)クラスのメンバ変数として定義するやり方です。変数の定義等は ClassWizard がやってくれるので、スコープの範囲内でその変数を使用することが出来ます。2つ目は次のようなコーディング方法です。こちらは初めに試みていたように、使いたいサブルーチン、スコープ内でその同型の変数を宣言し、そのポインタに使いたいコントロールをアタッチさせるやり方なので、頻繁には使わないなら、こちらの方がいいかも。デタッチをしないと、ややこしいことになるとの事なので、使わなくなったら必ずデタッチしましょう。

    CMyDialog::Function( .... )
    {
      CEdit edit;
    
      edit.Attach(::GetDlgItem(m_hWnd, IDC_EDIT));
    
      // edit 変数を使った様々な処理
    
      edit.Detach();
    }

 ちなみに、初めのやり方が間違いであると知ったのは、マイクロソフトジャーナルと言う、僕を含めてプログラムをちょっとかじった人では訳の分からない本の記事の中で見つけました。気合いの入っている人は購読するといいでしょう。発売間隔も長いので財布を圧迫することは無いと思います (^m^;


プログラム研究所

TOP-PAGE

Web-Page制作者e-mailアドレス