• ベストアンサー

【VC++6.0】イベントハンドラ関数を流用したいのですが、、、

VC++超初心者です。 既出の質問(http://okwave.jp/qa2658942.html)と同様ですが、VC2005(CLR)でなく、VC++6.0の時 どのようにコーディングすればよいか教えていただけませんでしょうか。 よろしくお願いします。 ********************************** 以下の2つのボタンのイベントハンドラ関数があった場合 //ボタン1のイベントハンドラ関数 void CAAAADlg::OnOK() { 処理内容 } //ボタン2のイベントハンドラ関数 void CBBBBDlg::OnOK() { } ボタン2をクリックしたときの動作とボタン1の動作を同じにしたいと思っています。 **********************************

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

  • ベストアンサー
  • BLK314
  • ベストアンサー率55% (84/152)
回答No.6

それではサンプルを載せます AAAADlg.cpp ここから ============================================== // AAAADlg.cpp : 実装ファイル // #include "stdafx.h" #include "DlgTest.h" #include "AAAADlg.h" // CAAAADlg ダイアログ IMPLEMENT_DYNAMIC(CAAAADlg, CDialog) CAAAADlg::CAAAADlg(CWnd* pParent /*=NULL*/) : CDialog(CAAAADlg::IDD, pParent) { } CAAAADlg::~CAAAADlg() { } void CAAAADlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAAAADlg, CDialog) END_MESSAGE_MAP() // CAAAADlg メッセージ ハンドラ AAAADlg.cpp ここまで ============================================== BBBBDlg.cpp ここから ============================================== #include "StdAfx.h" #include "resource.h" // これがないと'IDD_AAAA'が未定義のコンパイルエラーとなります #include "BBBBDlg.h" CBBBBDlg::CBBBBDlg(void) { } CBBBBDlg::~CBBBBDlg(void) { } void CBBBBDlg::OnOK() { if (AfxMessageBox(_T("ダイアログを閉じます。よろしいですか?"), MB_OKCANCEL) == IDCANCEL) return; CAAAADlg::OnOK(); } BBBBDlg.cpp ここまで ============================================== DlgTestDlg.cpp ここから============================================= // DlgTestDlg.cpp : 実装ファイル // #include "stdafx.h" #include "DlgTest.h" #include "DlgTestDlg.h" #include "BBBBDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // アプリケーションのバージョン情報に使われる CAboutDlg ダイアログ class CAboutDlg : public CDialog { public: CAboutDlg(); // ダイアログ データ enum { IDD = IDD_ABOUTBOX }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート // 実装 protected: DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() // CDlgTestDlg ダイアログ CDlgTestDlg::CDlgTestDlg(CWnd* pParent /*=NULL*/) : CDialog(CDlgTestDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CDlgTestDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CDlgTestDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_TEST, &CDlgTestDlg::OnBnClickedTest) END_MESSAGE_MAP() // CDlgTestDlg メッセージ ハンドラ BOOL CDlgTestDlg::OnInitDialog() { CDialog::OnInitDialog(); // "バージョン情報..." メニューをシステム メニューに追加します。 // IDM_ABOUTBOX は、システム コマンドの範囲内になければなりません。 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { BOOL bNameValid; CString strAboutMenu; bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX); ASSERT(bNameValid); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、 // Framework は、この設定を自動的に行います。 SetIcon(m_hIcon, TRUE); // 大きいアイコンの設定 SetIcon(m_hIcon, FALSE); // 小さいアイコンの設定 // TODO: 初期化をここに追加します。 return TRUE; // フォーカスをコントロールに設定した場合を除き、TRUE を返します。 } void CDlgTestDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // ダイアログに最小化ボタンを追加する場合、アイコンを描画するための // 下のコードが必要です。ドキュメント/ビュー モデルを使う MFC アプリケーションの場合、 // これは、Framework によって自動的に設定されます。 void CDlgTestDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // 描画のデバイス コンテキスト SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // クライアントの四角形領域内の中央 int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // アイコンの描画 dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // ユーザーが最小化したウィンドウをドラッグしているときに表示するカーソルを取得するために、 // システムがこの関数を呼び出します。 HCURSOR CDlgTestDlg::OnQueryDragIcon() { return static_cast<HCURSOR>(m_hIcon); } void CDlgTestDlg::OnBnClickedTest() { CBBBBDlg dlg; dlg.DoModal(); } DlgTestDlg.cpp ここまで============================================= AAAADlg.h ここから============================================= #pragma once // CAAAADlg ダイアログ class CAAAADlg : public CDialog { DECLARE_DYNAMIC(CAAAADlg) public: CAAAADlg(CWnd* pParent = NULL); // 標準コンストラクタ virtual ~CAAAADlg(); // ダイアログ データ enum { IDD = IDD_AAAA }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV サポート DECLARE_MESSAGE_MAP() }; AAAADlg.h ここまで============================================= BBBBDlg.h ここから============================================= #pragma once #include "aaaadlg.h" class CBBBBDlg : public CAAAADlg { public: CBBBBDlg(void); virtual ~CBBBBDlg(void); protected: virtual void OnOK(); }; BBBBDlg.h ここまで============================================= 以上は私が作成したサンプルの一部です。 きちんと動作確認してあります。 コンパイル・エラーは #include "BBBBDlg.h"の前に #include "resoure.h"がなかったためではないでしょうか? 注目して頂きたいのは CDlgTestDlg::OnBnClickedTest()の中身です。 CBBBBDlg dlg; dlg.DoModal(); ごく普通にCBBBBDlgを使っています (CAAAADlgは出てきていません) また CBBBBDlgのh/cppのどこでも "明示的には" CAAAADlgのコンストラクタを呼び出していないことにも注目です。 一見すると CAAAADlgをインスタンス化していない ように見えますが CBBBBDlgはCAAAADlgの派生なので CBBBBDlgのインスタンスの中にCAAAADlgのインスタンスがあります。 サンプルの概要はこうです CAAAADlgは"Hello World!"と表示するだけのダイアログで OKボタンのみ持っています。 これを一切いじれないものと仮定します。 CBBBBDlgは基本的にはCAAAADlgと全く同じです。 しかし、 OnOKでメッセージボックスを表示し 閉じてよいかの確認をする この点の差異があります。 >詳しい方にちょっとだけソースコードを見て頂いたら、 >CAAAADlgをインスタンス化していなから、 >CAAAADlg::OnOK()使えないと指摘を受けました。 C++ではクラスのメソッド呼び出しに class::method() が使用できます。これは上でみたように派生クラスのメソッド内部で 基本クラスのメソッドを呼び出す際に使われます。 また、staticなメソッドを呼ぶ際にも使えます。 この場合 インスタンス化していなくても、用いることが可能です。 ”詳しい方"はCに詳しい方ですか? Cに詳しい方がそのままC++にも詳しいとは限りません。 注意が必要です。

yuki7091
質問者

補足

長文にわたるご回答、ありがとうございます。 また、ご回答が遅れてしまい、申し訳ございませんでした。 本件は、結果的に他の方に任せてしまいましたが、 悔しいので自分でもやってみるつもりです。 また、この度、長文にわたって教えて頂いたソースも まだ理解できておりませんが、確実に糧にしていきたいと 思います。 >”詳しい方"はCに詳しい方ですか? >Cに詳しい方がそのままC++にも詳しいとは限りません。 >注意が必要です。 素人の私の意見ですが、私もそう思います。 私はC言語は学生の時からなんとなく使っていますが、 ・C++、 ・VC++(6.0)(MFCとういうのでしょうか?)、 ・VC++/CLI(VC++ .NET) これらは、かなり違うものなんだな、と感じています。 とにかく、勉強し直します。 今回は、No6さんの回答で本件を終了しますが、 また、宜しければご教授お願いします。 本当に、ご親切な対応ありがとうございました。

その他の回答 (5)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.5

CBBBBDlgがCAAAADlgを継承しているなら、CBBBBDlgのインスタンスはCAAAADlgのインスタンスを内包しています。なので、CAAAADlg::OnOK()はちゃんと呼び出せます。 そういう指摘受けたとしたら、ちゃんとCAAAADlgを継承していないのでは? どちらにしてもC++の知識が無さ過ぎますので、おっしゃってる関数化も多分無理だと思います。MFCの機能無しに関数化できますか?コントロールなどを参照もMFCを使えませんよ。 まぁ、後々の事を考えると関数化は止めといた方が良いと思いますが。最善の策はC++を勉強することです。あるいは、分る人に全部頼むかですね。

yuki7091
質問者

補足

ご回答、ありがとうございます。 (返信遅れてすみませんでした。) ご指摘のとおりだと思います。 C++はじっくり勉強していないので、 オブジェクト指向の考え方がいまいち理解しておりません。 時間をみつけて、勉強しなおします。

  • BLK314
  • ベストアンサー率55% (84/152)
回答No.4

簡単です。 しかも、質問者さんが (偶然かもしれませんが) 正解を出しています。 ただ、気づいていないのは (既にお気づきの場合はごめんなさい) CBBBBDlgをCAAAADlgから派生させる これだけです。 両者の基本クラスも必要ありませんし 既に作成してしまった CAAAADlg には一切手を加える必要はありません。 そして CBBBBDlgでOnOKをオーバーライドします。 中身は void CBBBBDlg::OnOK() { CBBBBDlgの専用処理(その1) CAAAADlg::OnOK() } です。 どこかで見たコードです。 補足そのものです。 ただ CAAAADlg::OnOK() であって CAAAADlg::OnOK() の処理内容 ではありません。 もちろん後者 CAAAADlg::OnOK() の処理内容 でも構いませんが、 後々(バグや仕様変更などで) CAAAADlg::OnOK() を修正した場合 CBBBBDlg::OnOK() も修正しなければならない というデメリットがあるので 前者 CAAAADlg::OnOK() をお勧めします。

yuki7091
質問者

補足

ご回答ありがとうございます。 (返信送れて申し訳ございませんでした。) なるほど、と思い早速コーディングしましたが、 コンパイルエラーが出てしまいました。 詳しい方にちょっとだけソースコードを見て頂いたら、 CAAAADlgをインスタンス化していなから、 CAAAADlg::OnOK()使えないと指摘を受けました。 やはり、動かしたい部分を関数化して切り出すしかないのでしょうか?

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

CAAAADlgとCBBBBdlgは親子関係あるのでしょうか まったく別物ということですか CAAAADlg::OnOKの中でCAAAADlgのコントロールなどを参照しているのですか たとえばどこかのテキストボックスの値のチェックとか

yuki7091
質問者

補足

ご回答、ありがとうございます。 >CAAAADlg::OnOKの中でCAAAADlgのコントロールなどを参照しているのですか 参照しています。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

まったく同じでないなら、CDialogクラスを継承してCAABBDlgと言うのを作って、共通な処理させるメンバ関数を例えばCAABBDlg::OkCom()と言う名前で作ります。 で、CAAAADlgとCBBBBDlgの親クラスをCAABBDlgに書き換えます。 で実際の呼び出しは、 void CAAAADlg::OnOK() { OkCom(); } void CBBBBDlg::OnOK() { CBBBBDlgの専用処理(その1) OkCom(); } ってするのはどうでしょか?

yuki7091
質問者

補足

ご回答、ありがとうございます。 他の方からも、zwiさんのようなアドバイスを頂きました。 void CAAAADlg::OnOK()は先人が書いたものなので、 個人的にはあまり手を加えたくありません。 そのため、CAAAADlg::OnOK()を呼び出せないかな、と 質問させていただきました。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

クラスが違うが同じ処理が必要な場合は、CAAAADlgとCBBBBDlgに共通の親クラスを作ってOnOK()を継承させれば解決すると思います。

yuki7091
質問者

補足

CAAAADlgはすでに作成済みであり、質問に書いた「処理内容」という 部分も大規模のものになっております。 それでも可能でしょうか? また、もう少し詳細をお話しすると CBBBBDlg::OnOK() の内部は、CAAAADlgと全く同じではなく、 void CBBBBDlg::OnOK() { CBBBBDlgの専用処理(その1) CAAAADlg::OnOK() の処理内容 } という具合にしたいです。

関連するQ&A